# A01: Broken Access Control Last updated: March 1, 2026 ## Findings 1. Cross-account delete risk in `/account/confirm-delete`. 2. `AUTH_DISABLED` mode allows header-based impersonation (`x-user-id`) and must be tightly controlled. ## Fixes implemented 1. `/account/confirm-delete` is now session-bound: - Lookup uses `req.userId`. - Request `email` must match session user's email. - Mismatch returns `403`. 2. Insecure auth guard added: - `AUTH_DISABLED=true` now requires `ALLOW_INSECURE_AUTH_FOR_DEV=true` unless `NODE_ENV=test`. 3. `/admin/rollover` hardened: - Still requires `AUTH_DISABLED=true`. - Now also requires request IP to be internal/private. ## Test coverage 1. `api/tests/access-control.account-delete.test.ts` - Verifies cross-account deletion attempt is denied (`403`). - Verifies victim account is not deleted. 2. `api/tests/auth.routes.test.ts` - Verifies protected route rejects unauthenticated access. - Verifies spoofed `x-user-id` is rejected when auth is enabled. - Verifies login/session/logout behavior with CSRF handling. - Verifies login lockout behavior. 3. `api/tests/access-control.admin-rollover.test.ts` - Verifies unauthenticated access to `/admin/rollover` is denied when `AUTH_DISABLED=false`. - Verifies authenticated access still receives `403` when `AUTH_DISABLED=false`. - Verifies `/admin/rollover` rejects non-internal client IP when `AUTH_DISABLED=true`. - Verifies `/admin/rollover` allows internal client IP when `AUTH_DISABLED=true`. ## Run commands From `api/`: ```bash npm test -- tests/auth.routes.test.ts tests/access-control.account-delete.test.ts tests/access-control.admin-rollover.test.ts ``` ## Expected results 1. All three test files pass. 2. No access granted to protected routes without valid auth cookie/JWT. 3. Spoofed `x-user-id` does not bypass auth when `AUTH_DISABLED=false`. 4. Cross-account delete attempt fails with `403`. 5. `/admin/rollover` remains inaccessible from public/non-internal clients. ## Production configuration requirements 1. `AUTH_DISABLED=false` 2. `ALLOW_INSECURE_AUTH_FOR_DEV=false` 3. Strong `JWT_SECRET` and `COOKIE_SECRET`