Security
Security model
- App passwords, Microsoft and Google tokens, webhook secrets and stored events are encrypted with AES-256-GCM under a master key you supply. Each value has a random nonce and is bound to its account.
- MCP access tokens, MCP refresh tokens, authorization codes and client
secrets are stored only as SHA-256 hashes. Codes are single use, refresh
tokens rotate on every use, and PKCE (
S256) is mandatory. Presenting a used code or refresh token again revokes the whole grant (RFC 9700 replay detection). - The sign-in page works without JavaScript and is served with a strict Content Security Policy (no inline script or style; only a small same-origin script for conveniences such as show/hide password). It can’t be framed. Failed sign-ins back off exponentially per client IP (up to 15 minutes) and per address (up to one minute, so nobody can lock you out); the OAuth endpoints are rate-limited per client IP, and client registrations are capped and expire when unused.
- The account page uses a short-lived session cookie (
__Host-prefixed over HTTPS,HttpOnly,SameSite=Lax; 1 hour idle, 12 hours at most) stored only as a hash. Every change needs a same-originOriginand a CSRF token, and destructive actions need explicit confirmation. - Webhooks go only to
httpsURLs on public addresses: private, loopback, link-local and cloud metadata addresses are refused, also after DNS resolution, and redirects are not followed. Events can be signed with HMAC-SHA256; the header value and signing secret are encrypted at rest. - An allow-list (
POSTKEEP_ALLOWED_EMAILS) limits which accounts can connect and is re-checked on every request. - Passwords, tokens and message contents are kept out of the logs (see the threat model).
- TLS uses rustls; there is no OpenSSL. The container runs as a non-root user on a distroless base.
Reporting a vulnerability
This project handles email credentials, so security reports are taken seriously.
Please do not open a public issue for security problems.
Report vulnerabilities privately with a confidential issue on GitLab: open https://gitlab.com/postkeep/postkeep/-/issues/new (you need to be signed in), tick This issue is confidential, and submit. It is then visible only to you and the project team.
Please include:
- a description of the issue and its impact,
- steps to reproduce or a proof of concept,
- affected versions or commits, if known.
Leave real credentials and app passwords out of the report. You should receive an acknowledgement within a few days. Once a fix is available, the maintainers will publish an advisory and credit you if you wish.
The project is in early development. Security fixes are made on the
main branch and released in the next version; only the latest release is
supported.
Further reading
- Threat model
- Security audit, October 2026
- Providers review, October 2026
- SECURITY.md in the repository