name: security-token-review description: Apply when changing credentials, OAuth, IMAP, env handling, API auth, or any path that touches secrets. Triggers on edits to src/server/security/crypto.ts, src/server/auth/oauth.ts, .env.example, next.config.mjs, src/app/api/connect/.
security-token-review
Source of truth: specs/product.md § Security; docs/architecture.md § Persistence and security.
When to invoke
- A cooperation plan touches credential storage, OAuth flow, env var coverage, or API auth.
- A new third-party SDK is introduced that may handle secrets.
- A reviewer suspects secret exposure in logs, error messages, or the client bundle.
Invariants
- AES-256-GCM is the only at-rest format for OAuth refresh tokens and IMAP passwords. Use
src/server/security/crypto.ts. TOKEN_ENCRYPTION_KEYis required in real-provider mode. Demo mode (DEMO_MODE=true) is the only path that may skip it.- Never put a secret into:
- A
console.log/console.warn/console.errorin a production route. - A response body returned to the client.
- A thrown error message that may surface to the client.
- A
Bashinvocation that prints to terminal in CI logs.
- A
ANTHROPIC_API_KEY,GOOGLE_CLIENT_SECRET,MICROSOFT_CLIENT_SECRET, IMAP passwords, refresh tokens are server-only..env.localis git-ignored. Theno-secret-commit.mjshook is the safety net, not the contract.APP_ACCESS_TOKENgates any non-public route if used; absence means routes are open (and that must be a deliberate decision).
Checklist
- New env vars added to
.env.examplewith placeholder values. - AES-256-GCM path used for any new credential.
- No logging of secret values introduced.
-
next.config.mjssecurity headers unchanged (or change explicitly justified). -
npm audit --omit=devclean. -
no-secret-commit.mjsdoes not flag the staged change.
Anti-patterns
- Storing a token "for now" in plaintext.
- Reading
TOKEN_ENCRYPTION_KEYon the client. - Adding a new env var without updating
.env.exampleandenv-check.mjs. - Catching crypto errors and silently continuing.