Skip to content

security: comprehensive security audit fixes#5

Closed
alfredocristofano wants to merge 5 commits into
raine:mainfrom
alfredocristofano:security-audit-fixes
Closed

security: comprehensive security audit fixes#5
alfredocristofano wants to merge 5 commits into
raine:mainfrom
alfredocristofano:security-audit-fixes

Conversation

@alfredocristofano

Copy link
Copy Markdown

Summary

This PR addresses findings from a comprehensive security audit of the proxy. All changes are defensive hardening with no breaking changes to the CLI or API surface.

Server & DoS Hardening

  • Body size limit: capped at 10 MiB to prevent OOM via req.json() on huge payloads
  • Session map eviction: sessionSeqs and sessionTimeline now have size limits and periodic cleanup to prevent unbounded memory growth
  • Session ID validation: restricted to 128 chars and [a-zA-Z0-9_-] to prevent key injection and memory exhaustion
  • SSE buffer limit: capped at 10 MiB to avoid unbounded accumulation when upstream never sends a boundary

Information Disclosure

  • Generic error messages: 500 and 404 responses no longer leak internal error details or path info
  • Query string removed from logs: url.search no longer logged to avoid accidental secret leakage
  • Expanded log redaction: added password, secret, api_key, cookie, bearer, token, and more to REDACT_KEYS
  • Circular reference safety: JSON.stringify in logger now handles cyclic objects without crashing
  • Log file permissions: directory created with 0o700, log file with 0o600

Authentication & OAuth

  • PKCE randomness: eliminated modulo bias by using base64url encoding of random bytes directly; increased verifier length to 128
  • Ephemeral OAuth port: replaced hardcoded port 1455 with dynamic port 0 to prevent port squatting
  • OAuth callback validation: added Host header validation and HTML-escaping of error messages
  • Token invalidation: Codex auth manager now clears stored tokens on 401/403 refresh failures
  • Storage directory permissions: Linux auth directories created with 0o700

Input Validation

  • Anthropic body validation: runtime checks for model, messages, max_tokens, temperature, top_p, and tools
  • Image URL validation: only http:, https:, and data: URLs are forwarded upstream
  • Missing source guard: imageToUrl no longer crashes on malformed image blocks
  • Safe JSON stringify: JSON.stringify in request builders wrapped to survive circular inputs
  • Retry-after validation: numeric format enforced before reflecting upstream rate-limit headers

CI/CD & Supply Chain

  • Least-privilege permissions: workflow-level contents: read, write only on release and update-tap jobs
  • Pinned Bun version: CI and packageManager field locked to 1.3.10
  • Pinned @types/bun: moved from latest to exact version 1.3.12
  • Regenerated bun.lock: fixed stale project name mismatch
  • Added private: true, engines, packageManager, and repository metadata to package.json
  • Job timeouts: added timeout-minutes to all workflow jobs
  • Expanded .gitignore: excludes logs, env files, auth artifacts

Test Plan

  • bun run typecheck passes
  • Server starts and /healthz responds correctly
  • bun install --frozen-lockfile works with regenerated lockfile

Notes

The macOS Keychain security CLI still passes tokens as command-line arguments (visible via ps). Fixing this requires migrating to a native Keychain API, which is left as a follow-up due to dependency complexity.

alfredocristofano and others added 5 commits April 24, 2026 23:07
- Add 10 MiB body size limit to prevent OOM
- Validate sessionId length/format and cap sessionSeqs map size
- Return generic 500/404 messages instead of internal details
- Strip query string from request logs
- Add security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
- Filter sensitive upstream headers (set-cookie, server, via, x-request-id)
- Add runtime validation for Anthropic request body

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Expand REDACT_KEYS with password, secret, api_key, cookie, bearer, etc.
- Handle circular references in JSON.stringify to prevent crashes
- Enforce 0o700 on log directory and 0o600 on log file
- Add 10 MiB limit to SSE buffer to prevent unbounded growth

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix PKCE randomness bias by using base64url encoding directly
- Use ephemeral port 0 for OAuth callback to prevent port squatting
- Validate Host header in OAuth callback server
- HTML-escape error messages in OAuth callback response
- Clear stored Codex tokens on 401/403 refresh failure
- Enforce 0o700 on auth storage directories on Linux

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add safeJsonStringify helper to prevent crashes on circular refs
- Validate image URLs before forwarding (allow http/https/data only)
- Guard against missing image block source
- Validate retry-after header format before reflection
- Add sessionTimeline eviction to prevent unbounded memory growth
- Remove raw console.error(err) in CLI that bypassed log redaction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add private: true, engines, packageManager, and repository metadata
- Pin @types/bun to exact version and regenerate bun.lock
- Reduce CI workflow permissions to least-privilege per job
- Pin Bun version in CI for reproducible builds
- Add timeout-minutes to all CI jobs
- Expand .gitignore to exclude logs, env files, and auth artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@raine

raine commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR. I'm reluctant to take changes like this in directly, and rather do things with my own workflow which I trust. Running the findings through my own review process and applying what makes sense to me. I've already done a security hardening pass in main and addressed some things.

@raine raine closed this Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants