Skip to content

fix: express csurf#83

Merged
rongquan1 merged 8 commits intomasterfrom
fix/express-csurf
Oct 29, 2025
Merged

fix: express csurf#83
rongquan1 merged 8 commits intomasterfrom
fix/express-csurf

Conversation

@RishabhS7
Copy link
Contributor

@RishabhS7 RishabhS7 commented Oct 29, 2025

Summary

Revert the cookies config to hardcoded

Summary by CodeRabbit

  • Chores
    • Added origin and referrer validation checks to API routes through new middleware
    • Implemented API key authentication for verification endpoints with support for machine-to-machine requests via valid API keys
    • Updated integration tests across all verification scenarios (mainnet, astrontestnet, and general verification endpoints) to include API key authentication headers

@netlify
Copy link

netlify bot commented Oct 29, 2025

Deploy Preview for tradetrust-functions ready!

Name Link
🔨 Latest commit 946cf02
🔍 Latest deploy log https://app.netlify.com/projects/tradetrust-functions/deploys/6901e167f8a8fc0008587e12
😎 Deploy Preview https://deploy-preview-83--tradetrust-functions.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Walkthrough

The PR introduces origin and referrer validation middleware and M2M (machine-to-machine) CSRF bypass logic. New originReferrerGuard middleware validates request origins against trusted origins, allowing M2M requests with valid API keys to bypass CSRF validation. The middleware is applied to storage and verify routes, and integration tests are updated to include API key headers in requests.

Changes

Cohort / File(s) Summary
Origin validation middleware
netlify/utils.ts
Added isTrustedOrigin() and originReferrerGuard() middleware for validating request origins against ALLOWED_ORIGIN_REGEX or localhost; allows M2M bypass with valid API key. Expanded getDocumentData() return type to support additional document types.
Storage router enhancements
netlify/functions/storage/router.ts
Applied originReferrerGuard to POST "/" and POST "/:id" routes alongside existing CSRF middleware. Enhanced CSRF endpoint to include originReferrerGuard and checkApiKey, with cookie scoping to storage function path. Added M2M pre-check to bypass CSRF validation.
Verify router enhancements
netlify/functions/verify/router.ts
Added originReferrerGuard middleware to POST / route before handler execution.
Integration test updates
tests/integration/document-astron-verify.test.ts, tests/integration/document-astrontestnet-verify.test.ts, tests/integration/document-verify.test.ts
Added x-api-key header from process.env.API_KEY to all POST requests across verification test cases to enable API key authentication.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Guard as originReferrerGuard
    participant CSRFMiddleware as CSRF Validation
    participant Route as Route Handler

    Client->>Guard: POST request with Origin/Referer
    Guard->>Guard: Extract origin candidate
    
    alt Valid API Key (M2M)
        Guard->>Guard: Extract API key from header
        Guard->>Guard: Validate API key
        Guard->>Route: Allow request (bypass CSRF)
    else No API Key or Invalid
        Guard->>Guard: Validate origin against ALLOWED_ORIGIN_REGEX
        alt Trusted Origin
            Guard->>CSRFMiddleware: Proceed to CSRF validation
            CSRFMiddleware->>Route: CSRF token valid
        else Untrusted/Missing Origin
            Guard->>Client: 403 Forbidden
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring extra attention:

  • Security logic in originReferrerGuard() for origin validation and M2M bypass mechanism
  • CSRF middleware pre-check implementation and M2M logic flow
  • API key validation against untrusted origins in the storage and verify routers
  • Consistent API key header application across all integration test scenarios

Possibly related PRs

Suggested reviewers

  • rongquan1

Poem

🐰✨ A guard arrives at every gate,
Checking origins—early, not late,
M2M keys are welcome friends,
Trusted routes, where trust extends,
Security hops with gentle might! 🛡️

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is largely incomplete and does not follow the provided template. Only the Summary section is present with a single, minimal line ("Revert the cookies config to hardcoded"), while the required Changes and Issues sections are entirely missing. Additionally, there is a significant discrepancy between the description's claim of reverting cookies configuration and the actual changeset, which involves adding origin/referrer guard middleware, enhancing CSRF validation with M2M bypass logic, and updating multiple router files and integration tests. The description provides insufficient context about the changes or their purpose. Expand the pull request description to follow the template structure. The Summary should explain the background and motivation, the Changes section should detail all modifications (adding origin/referrer guard middleware, updating CSRF validation, adding API key authentication to tests, etc.), and the Issues section should reference any related issues or stories. This will provide reviewers with a clear understanding of the changes and their rationale.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "fix: express csurf" does relate to the actual changes, which involve enhancing CSRF protection through the addition of origin/referrer guard middleware and M2M bypass logic. However, the title is quite vague and generic—it doesn't clearly communicate what specific aspect of CSRF handling is being fixed. A reader would need to review the actual code to understand that this involves adding origin validation guards and updating CSRF middleware behavior. The title refers to a real aspect of the changes but lacks the specificity needed to clearly summarize the main improvements being made.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/express-csurf

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
netlify/utils.ts (1)

47-53: CRITICAL: Fix API key validation vulnerability.

If process.env.API_KEY is undefined (not set), requests without an API key will pass validation since undefined !== undefined evaluates to false. This creates a security vulnerability where the API becomes unprotected if the environment variable is not configured.

Apply this diff to fix the vulnerability:

 export const checkApiKey = (req, res, next) => {
   const apiKey = req.headers["x-api-key"];
-  if (apiKey !== process.env.API_KEY) {
+  if (!process.env.API_KEY || apiKey !== process.env.API_KEY) {
     return res.status(400).send(ERROR_MESSAGE.API_KEY_INVALID);
   }
   next();
 };

Alternatively, add a startup validation to ensure API_KEY is always set in production environments.

🧹 Nitpick comments (2)
netlify/utils.ts (1)

88-93: Clarify error message for invalid API key.

When an API key is provided but invalid, the error message "Missing Origin/Referer" is misleading. Consider returning a more accurate message that indicates either the Origin/Referer is missing OR the API key is invalid.

Apply this diff to improve the error message:

   if (!candidateOrigin) {
     // Allow M2M (non-browser) requests without Origin/Referer only if API key is valid
     const apiKey = req.headers["x-api-key"] as string | undefined;
     if (apiKey && apiKey === process.env.API_KEY) return next();
-    return res.status(403).json({ error: "Missing Origin/Referer" });
+    return res.status(403).json({ error: "Missing or invalid Origin/Referer or API key" });
   }
netlify/functions/storage/router.ts (1)

64-72: Consider consolidating M2M bypass logic.

The M2M bypass logic (checking for no Origin/Referer + valid API key) is duplicated here and in originReferrerGuard. Since originReferrerGuard is already applied to these routes (lines 96, 115), the M2M requests will pass through it. You could simplify this middleware by relying on a request property set by originReferrerGuard instead of re-checking headers.

Example approach:

+// In originReferrerGuard (utils.ts):
+  if (!candidateOrigin) {
+    const apiKey = req.headers["x-api-key"] as string | undefined;
+    if (apiKey && apiKey === process.env.API_KEY) {
+      req.isM2MRequest = true;  // Mark as M2M
+      return next();
+    }
+    return res.status(403).json({ error: "Missing Origin/Referer" });
+  }

 // In csrfValidationMiddleware:
-  const originHeader = req.headers.origin as string | undefined;
-  const refererHeader = req.headers.referer as string | undefined;
-  const apiKey = req.headers["x-api-key"] as string | undefined;
-
-  // If no Origin/Referer and valid API key, skip CSRF validation (M2M request)
-  if (!originHeader && !refererHeader && apiKey === process.env.API_KEY) {
+  // Skip CSRF validation for M2M requests
+  if (req.isM2MRequest) {
     return next();
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1227ee and 946cf02.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • netlify/functions/storage/router.ts (4 hunks)
  • netlify/functions/verify/router.ts (1 hunks)
  • netlify/utils.ts (3 hunks)
  • tests/integration/document-astron-verify.test.ts (4 hunks)
  • tests/integration/document-astrontestnet-verify.test.ts (4 hunks)
  • tests/integration/document-verify.test.ts (10 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
netlify/utils.ts (1)
netlify/constants.ts (2)
  • ALLOWED_ORIGIN_REGEX (5-6)
  • LOCALHOST_ORIGINS (8-11)
netlify/functions/verify/router.ts (1)
netlify/utils.ts (1)
  • originReferrerGuard (70-100)
netlify/functions/storage/router.ts (1)
netlify/utils.ts (2)
  • originReferrerGuard (70-100)
  • checkApiKey (47-53)
🔇 Additional comments (11)
netlify/utils.ts (4)

18-18: LGTM: Express types imported for middleware.

The Express type imports are correctly added to support the new middleware signatures.


55-68: LGTM: Origin validation logic is sound.

The isTrustedOrigin function correctly:

  • Handles both full URLs and origin strings
  • Validates against the allowed regex pattern
  • Permits localhost only in test environments
  • Uses safe URL parsing with try-catch

70-100: LGTM: M2M bypass logic correctly implemented.

The originReferrerGuard middleware correctly:

  • Validates Origin header first, falls back to Referer
  • Allows M2M requests with valid API key when Origin/Referer is missing
  • Rejects untrusted origins
  • Uses proper Express typing

108-116: LGTM: Return type broadened safely.

The addition of unknown to the return type makes the signature more accurate without changing the runtime behavior.

netlify/functions/storage/router.ts (3)

2-2: LGTM: originReferrerGuard applied to POST routes.

The middleware is correctly applied to the storage POST routes, providing origin/referrer validation with M2M bypass support.

Also applies to: 96-96, 115-115


43-49: LGTM: CSRF cookie properly configured.

The cookie configuration is secure:

  • httpOnly: true prevents JavaScript access
  • secure: true ensures HTTPS-only
  • sameSite: "None" allows cross-origin (required with secure)
  • Path scoped to /.netlify/functions/storage
  • 1-hour expiration

34-56: I need to verify whether this repository contains frontend/browser client code that might be affected by this change.

Let me check the actual repository structure to determine if this is a backend-only service:

CSRF token endpoint requires API key—verify integration impact with your frontend/browser clients.

All tests show that CSRF tokens are obtained with both originReferrerGuard and checkApiKey middleware, which is intentional for this API architecture. However, this breaks the traditional CSRF pattern where browsers obtain tokens before authenticating.

If your frontend clients or browser-based integrations need to:

  • Obtain CSRF tokens without an API key
  • Make unauthenticated cross-origin requests

Then consider removing checkApiKey from the /csrf-token endpoint OR update your frontend to acquire API keys before fetching CSRF tokens. Document your intended authentication flow for clarity.

netlify/functions/verify/router.ts (1)

2-2: LGTM: originReferrerGuard applied to verify endpoint.

The middleware correctly protects the verify endpoint by allowing:

  1. Browser requests from trusted origins (with or without API key)
  2. M2M requests with valid API key (no Origin/Referer required)

This is appropriate for a verification endpoint that should be accessible to both browser clients and programmatic API consumers.

Also applies to: 7-7

tests/integration/document-verify.test.ts (1)

34-34: LGTM: Tests updated for API key authentication.

All POST requests now include the x-api-key header, correctly simulating M2M requests. This aligns with the new originReferrerGuard middleware that requires either a trusted Origin/Referer or a valid API key.

Also applies to: 44-44, 52-52, 63-63, 74-74, 85-85, 96-96, 107-107, 118-118, 129-129, 140-140

tests/integration/document-astron-verify.test.ts (1)

24-24: LGTM: Tests updated for API key authentication.

All POST requests now include the x-api-key header, consistent with the new authentication requirements. The formatting improvements to the request chains also enhance readability.

Also applies to: 34-34, 42-42, 53-53, 64-64, 75-75

tests/integration/document-astrontestnet-verify.test.ts (1)

24-24: LGTM: Tests updated for API key authentication.

All POST requests now include the x-api-key header, completing the test suite updates to align with the new origin/referrer validation and M2M authentication flow.

Also applies to: 34-34, 42-42, 53-53, 64-64, 75-75

@rongquan1 rongquan1 merged commit c9df080 into master Oct 29, 2025
10 checks passed
@rongquan1 rongquan1 deleted the fix/express-csurf branch October 29, 2025 09:51
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