Skip to content

fix(api): harden CSRF middleware and normalize CSRF errors for production#27

Merged
BODMAT merged 8 commits into
masterfrom
fix/security-email
May 6, 2026
Merged

fix(api): harden CSRF middleware and normalize CSRF errors for production#27
BODMAT merged 8 commits into
masterfrom
fix/security-email

Conversation

@BODMAT
Copy link
Copy Markdown
Owner

@BODMAT BODMAT commented May 5, 2026

Description

Addresses 4 CodeQL security alerts and 7 npm audit vulnerabilities. Rewrites the CSRF middleware to use proper double-submit cookie token validation (csrf-csrf v4), normalizes CSRF errors so they always surface as structured 403 responses in production, and closes remaining security gaps flagged by static analysis.

Changes by area:

  • CSRF — replaced origin-based bypass logic with doubleCsrf token validation; added GET /api/csrf-token endpoint; web client now caches and injects the token on every mutation, with automatic retry on 403
  • Error normalizationdoubleCsrfProtection is now wrapped in app.ts to convert raw HttpError into AppError("CSRF validation failed", 403) so the global error handler always returns a consistent JSON shape
  • Helmet — fixed contentSecurityPolicy: false in dev (CodeQL alert fix(vercel): stabilize basePath redirects and polish auth/profile UI #19) by using explicit CSP directives; changed crossOriginResourcePolicy from cross-origin to same-origin
  • Rate limiting — added userMutationLimiter (60 req / 15 min) to PATCH /me, DELETE /me, DELETE /me/auth-methods/:id (CodeQL alert chore(api): harden docs/dev tooling, add system health docs, and clean up user/admin routes #20)
  • Double-escaping — renamed sanitizeTextdecodeHtmlEntities and removed &lt;/&gt;</> reversal that re-introduced unescaped HTML (CodeQL alert Seed: UserApiKey records fail to decrypt with different API_KEY_ENCRYPTION_SECRET #17)
  • npm audit — resolved 7 vulnerabilities (2 low, 4 moderate, 1 high) via overrides for nodemailer, postcss, next, axios; CI audit job now blocks at --audit-level=moderate without continue-on-error

Resolves CodeQL alerts #17, #18, #19, #20 (Security tab)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)

How Has This Been Tested?

  • Unit tests (Jest/Vitest)
  • Integration tests
  • Manual testing (screenshots/screencasts encouraged)

API (Jest): rewrote security.middleware.test.ts to use doubleCsrfProtection directly — verifies that a missing CSRF token on a mutation request calls next with a 403 error, and that the Stripe webhook path bypasses CSRF. All 59 API tests pass.

Web (Vitest): updated api.test.ts mock to include interceptors.request.use for the new CSRF interceptor. All 19 web tests pass.

To reproduce locally:

npm run test:api   # 59 passing
npm run test:web   # 19 passing
npm audit          # 0 vulnerabilities

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have documented non-obvious behavior or constraints where necessary
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • (If API) Database migrations have been created and tested
  • (If UI) Changes look good on mobile and desktop

@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fin-track-web Ready Ready Preview, Comment May 5, 2026 10:35pm

Comment thread apps/api/src/app.ts Fixed
Comment thread apps/api/src/app.ts Fixed
… and webhook

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@BODMAT BODMAT marked this pull request as ready for review May 5, 2026 22:40
@BODMAT BODMAT requested a review from dzhhem May 5, 2026 22:40
@BODMAT
Copy link
Copy Markdown
Owner Author

BODMAT commented May 5, 2026

Opened follow-up tracking issue for upstream audit advisory (GHSA-v2v4-37r5-5v8g): #28. We’ll remove the temporary CI exception once upstream is fixed.

@BODMAT BODMAT merged commit 1b19576 into master May 6, 2026
14 checks passed
@BODMAT BODMAT deleted the fix/security-email branch May 6, 2026 12:04
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.

3 participants