# A09: Security Logging and Monitoring Failures Last updated: March 1, 2026 ## Findings addressed 1. Security-sensitive auth/account outcomes were not consistently logged as structured audit events. 2. Incident triage required better request correlation for failed auth/CSRF and account-deletion attempts. ## Fixes implemented 1. Added centralized structured security logging helper in API: - `logSecurityEvent(req, event, outcome, details)` - Includes request correlation fields (`requestId`, `ip`, `userAgent`). 2. Added audit logging for critical security events: - `auth.unauthenticated_request` (JWT auth failure) - `csrf.validation` (CSRF check failure) - `auth.register` success/blocked - `auth.login` success/failure/blocked (including lockout cases) - `auth.logout` success - `auth.verify` success/failure - `auth.verify_resend` success/failure/blocked - `auth.password_reset.request` success/blocked - `auth.password_reset.email` success/failure - `auth.password_reset.confirm` success/failure - `account.delete_request` success/failure/blocked - `account.confirm_delete` success/failure/blocked 3. Reduced sensitive data exposure in logs: - Added email fingerprinting (`sha256` prefix) for event context instead of plain-text credentials. ## Files changed 1. `api/src/server.ts` 2. `api/tests/security-logging-monitoring-failures.test.ts` 3. `api/vitest.security.config.ts` 4. `api/tests/forgot-password.security.test.ts` 5. `SECURITY_FORGOT_PASSWORD.md` ## Verification Command: ```bash cd api npx vitest run -c vitest.security.config.ts tests/security-logging-monitoring-failures.test.ts ``` Verified output: - Test Files: `1 passed (1)` - Tests: `2 passed (2)` Dedicated A09 checks in `security-logging-monitoring-failures.test.ts`: 1. Runtime check emits structured `auth.unauthenticated_request` security event for protected-route access failures. 2. Runtime check emits structured `csrf.validation` security event for CSRF failures. 3. Validates correlation fields (`requestId`, `ip`, `outcome`) are present in emitted security events. 4. Runtime check emits `auth.password_reset.request` events and confirms raw token fields are absent. ## Residual notes 1. Event logs are currently emitted through app logs; ensure production log shipping/alerting (e.g., SIEM rules on repeated `auth.login` failure/blocked events). 2. Next step for A09 maturity is alert thresholds and automated incident notifications.