chore: root commit of OWSAP security testing/tightening
All checks were successful
Deploy / deploy (push) Successful in 1m42s
Security Tests / security-non-db (push) Successful in 20s
Security Tests / security-db (push) Successful in 22s

This commit is contained in:
2026-03-01 20:46:47 -06:00
parent 1645896e54
commit 079b8b9492
25 changed files with 1131 additions and 107 deletions

View File

@@ -0,0 +1,71 @@
# A04: Cryptographic Failures
Last updated: March 1, 2026
## Findings addressed
1. Production origin could be configured as non-HTTPS.
2. JWT configuration did not explicitly constrain issuer/audience/algorithm.
3. Missing explicit env contract for JWT issuer/audience values.
## Fixes implemented
1. Production HTTPS origin enforcement:
- Added production guard requiring `APP_ORIGIN` to start with `https://`.
2. JWT hardening in Fastify:
- Explicit signing algorithm set to `HS256`.
- JWT signing includes configured `iss` and `aud`.
- JWT verification enforces:
- allowed algorithm (`HS256`)
- allowed issuer
- allowed audience
3. Env schema expanded:
- Added `JWT_ISSUER` and `JWT_AUDIENCE` with secure defaults:
- `skymoney-api`
- `skymoney-web`
## Files changed
1. `api/src/env.ts`
2. `api/src/server.ts`
3. `.env.example`
4. `api/tests/cryptographic-failures.test.ts`
5. `api/tests/cryptographic-failures.runtime.test.ts`
6. `api/vitest.security.config.ts`
## Verification
Commands:
```bash
cd api
npx vitest run -c vitest.security.config.ts tests/cryptographic-failures.test.ts tests/cryptographic-failures.runtime.test.ts
```
Verified output:
- Test Files: `2 passed (2)`
- Tests: `7 passed (7)`
Dedicated A04 checks in `cryptographic-failures.test.ts`:
1. Production env rejects non-HTTPS `APP_ORIGIN`.
2. JWT issuer/audience defaults resolve as expected.
3. Fastify JWT plugin is registered with explicit algorithm + issuer + audience constraints.
Runtime adversarial checks in `cryptographic-failures.runtime.test.ts`:
1. Token with invalid issuer is rejected (`401`).
2. Token with invalid audience is rejected (`401`).
3. Unsigned token (`alg=none`) is rejected (`401`).
4. Token with valid signature + expected issuer/audience is accepted on protected auth refresh route.
## Required production env values
1. `APP_ORIGIN=https://...`
2. `JWT_SECRET` strong 32+ chars
3. `COOKIE_SECRET` strong 32+ chars
4. `JWT_ISSUER=skymoney-api` (or your approved value)
5. `JWT_AUDIENCE=skymoney-web` (or your approved value)