Skip to content

Security review — PR #22 (retroactive): 3 Medium / 3 Low / 1 Info #26

Description

@pulkitpareek18

Retroactive security review of PR #22 (Central API developer console — merged as 0c325fb, live at 0d1741d).

Discipline-debt clearance — PR #22 touched all four security-reviewer trigger surfaces (auth, crypto, audit, tenant boundaries) and merged without the subagent running, against the standing instruction in CLAUDE.md.

Full report (with reproduction steps + remediation for each finding) lives at qa-log/security-review-pr22.md.

Net assessment

Medium risk overall. No Critical findings. No tenant API key rotation required. Tenant scoping (the load-bearing security property) is correctly enforced; the tests/console-proxy.test.ts suite already covers A-01 + A-10 scoping. The actual issues are documentation drift, an enumeration channel, and an attribution gap on the audit log.

Findings (action items)

Medium — land this week

  • F-1: Console JWT stored in localStorage; docs/threat_model.md A-09 claims "client memory" → either move to HttpOnly cookies OR update A-09 to match implementation. Run threat-model-update, file an ADR.
  • F-2: Email enumeration on /api/console/signup → return uniform 202 regardless of email existence; emit verification email out-of-band.
  • F-3: Console-initiated audit rows show actor_type='api_key' with actor_id=NULL → plumb actorType: 'console' + actorEmail through platform.ts and recordAuditEvent.

Low — land next week or fold into related work

  • F-4: Add per-tenant write rate-limit (60/15min by req.console.tenantId) on POST/PATCH/DELETE in src/routes/console.ts.
  • F-5: Add jti + aud='zeroauth-console' to console JWT; verify aud in verifyConsoleToken; Redis-backed jti revocation list.
  • F-6: Validate ?limit= query param in 5 console handlers; reject with 400 invalid_limit instead of relying on sanitizeLimit downstream.

Informational

  • F-7: Two console handlers use the error: field for human strings; convention is { error: '<machine_code>', message: '<human>' }.

Things checked + clean (8 items)

See report. Highlights: every SQL query in platform.ts is pg-parameterised + tenant-scoped; no dangerouslySetInnerHTML anywhere in dashboard; no JWT or password in log lines; Helmet CSP + trust proxy 1 correctly set behind Caddy.

Recommendations beyond findings

  • Run threat-model-update skill to reconcile A-09 with shipped reality.
  • Adopt zod via dep-add for the 8+ repeated if (!field) checks in console.ts.
  • Add CSP report-uri (open item in threat model).

Subagent

Continuation reference: agentId acdae2de12c322caa — use SendMessage to resume the same security-reviewer session with follow-up questions.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity finding or hardening

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions