Skip to content

Conversation

@vasilyyaremchuk
Copy link
Collaborator

And Error on the site message: CSRF exception

apos-module-bundle.js:3 POST https://speedandfunction.com/api/v1/@apostrophecms/login/context?aposLocale=en 403 (Forbidden)

@vasilyyaremchuk vasilyyaremchuk requested a review from killev as a code owner August 5, 2025 04:09
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 5, 2025

📝 Walkthrough

Walkthrough

The configuration function for the ApostropheCMS app was updated to introduce environment-aware settings, enhanced session and CSRF cookie security, proxy support, and custom CORS handling. Middleware was added to adjust headers for custom domains and API requests. Minor formatting changes and widget declaration adjustments were also made. Extensive new tests were added to verify environment-dependent configuration, cookie and CSRF settings, token extraction, and middleware behavior.

Changes

Cohort / File(s) Change Summary
App Configuration and Middleware
website/app.js
Enhanced createAposConfig with environment detection, dynamic baseUrl, proxy support, improved session and CSRF cookie settings, expanded CSRF options, and new middleware for proxy header and CORS management. Minor formatting and widget declaration adjustments.
Test Coverage for Configuration and Middleware
website/app.test.js
Added extensive tests covering environment-based baseUrl defaults, trustProxy setting, session and CSRF cookie attributes, CSRF token extraction from multiple locations, middleware header adjustments for custom domains, and CORS header application for allowed origins. Confirmed middleware order and presence.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ExpressServer
    participant Middleware
    participant ApostropheCMS

    Client->>ExpressServer: HTTP Request
    ExpressServer->>Middleware: Apply proxy & CORS middleware
    Middleware->>ExpressServer: Adjust headers, set CORS if API
    ExpressServer->>Middleware: CSRF middleware
    Middleware->>ExpressServer: Validate CSRF (with enhanced extraction)
    ExpressServer->>ApostropheCMS: Route handling
    ApostropheCMS-->>ExpressServer: Response
    ExpressServer-->>Client: HTTP Response (with secure cookies)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

  • [679-1] set csrf protection #176: The main PR extends and refines the CSRF protection configuration introduced in the retrieved PR [679-1] set csrf protection #176 by adding more detailed cookie settings, CSRF token extraction logic, and middleware for proxy and CORS handling, directly building upon the same @apostrophecms/express CSRF configuration.

Suggested reviewers

  • yuramax

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96aa47d and 074329a.

📒 Files selected for processing (1)
  • website/app.test.js (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: applies to **/*.e2e.{js,jsx} : e2e test files: relaxed import, ternary, and sorting rules...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to **/*.e2e.{js,jsx} : E2E test files: relaxed import, ternary, and sorting rules

Applied to files:

  • website/app.test.js
📚 Learning: applies to **/*.test.{js,jsx} : test files have relaxed rules for function length, statements, extra...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to **/*.test.{js,jsx} : Test files have relaxed rules for function length, statements, extraneous requires, and destructuring

Applied to files:

  • website/app.test.js
📚 Learning: for the speed and function website project, the server is managed through docker containers rather t...
Learnt from: IhorMasechko
PR: speedandfunction/website#12
File: website/playwright.config.js:11-30
Timestamp: 2025-04-18T14:26:08.447Z
Learning: For the Speed and Function website project, the server is managed through Docker containers rather than using Playwright's webServer configuration option. The testing environment stays consistent across tests as long as the containers are running.

Applied to files:

  • website/app.test.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint
  • GitHub Check: unit-tests
  • GitHub Check: e2e-tests
  • GitHub Check: security-scan
🔇 Additional comments (8)
website/app.test.js (8)

1-163: LGTM! Comprehensive existing test coverage maintained.

The existing test suite provides thorough coverage of the basic configuration functionality, module presence validation, and widget configurations. The structure using test.each and describe.each for testing multiple scenarios is well-implemented.


165-203: Excellent environment-aware configuration testing.

The test suite thoroughly covers all baseUrl configuration scenarios including production/development environments and BASE_URL precedence. Proper environment cleanup prevents test pollution.


205-211: LGTM! Trust proxy configuration properly tested.

Simple but important test ensuring the trust proxy setting is enabled, which is crucial for production deployments behind reverse proxies.


213-251: Excellent cookie security configuration testing.

The tests properly validate environment-specific cookie settings with appropriate security measures:

  • Production uses secure cookies with domain configuration for speedandfunction.com
  • Development uses non-secure cookies for localhost
  • Consistent security attributes (httpOnly, sameSite) across environments

This directly addresses the production login domain issues mentioned in the PR objectives.


253-286: Critical CSRF cookie configuration properly tested.

These tests validate the CSRF cookie settings that directly address the 403 Forbidden CSRF exceptions mentioned in the PR objectives. The environment-specific domain configuration for production (speedandfunction.com) should resolve the cross-domain CSRF issues.


288-367: Comprehensive CSRF token extraction testing.

The tests thoroughly validate CSRF token extraction from multiple sources (body, query, headers) with proper prioritization. This flexible token acceptance should help resolve the CSRF validation issues described in the PR by accommodating different client-side token submission methods.


369-422: Well-tested hostname middleware for production domain handling.

The middleware tests properly validate the logic for detecting and handling requests from the production domain (speedandfunction.com). The header manipulation (x-forwarded-host/proto) ensures proper upstream request handling, which is crucial for resolving domain-related issues in production.


424-503: Excellent CORS middleware testing for cross-origin CSRF resolution.

The CORS tests comprehensively validate the middleware that enables cross-origin requests between the production domain and Railway app. Key features properly tested:

  • Credential support for session/CSRF cookies
  • CSRF token headers in allowed headers
  • Proper middleware ordering (before CSRF middleware)
  • Secure origin allowlist

This middleware configuration is essential for resolving the cross-domain CSRF 403 errors mentioned in the PR objectives.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch production-cors-issue

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Aug 5, 2025

🔍 Vulnerabilities of apostrophe-cms:test

📦 Image Reference apostrophe-cms:test
digestsha256:5622f7f61e30c116a38c8637d20ede2a8247222ad697da9e9b8ef36c648070fd
vulnerabilitiescritical: 1 high: 4 medium: 0 low: 0
platformlinux/amd64
size291 MB
packages984
📦 Base Image node:23-alpine
also known as
  • 23-alpine3.22
  • 23.11-alpine
  • 23.11-alpine3.22
  • 23.11.1-alpine
  • 23.11.1-alpine3.22
digestsha256:b9d38d589853406ff0d4364f21969840c3e0397087643aef8eede40edbb6c7cd
vulnerabilitiescritical: 0 high: 0 medium: 1 low: 1
critical: 1 high: 0 medium: 0 low: 0 form-data 4.0.2 (npm)

pkg:npm/form-data@4.0.2

critical 9.4: CVE--2025--7783 Use of Insufficiently Random Values

Affected range>=4.0.0
<4.0.4
Fixed version4.0.4
CVSS Score9.4
CVSS VectorCVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
EPSS Score0.076%
EPSS Percentile24th percentile
Description

Summary

form-data uses Math.random() to select a boundary value for multipart form-encoded data. This can lead to a security issue if an attacker:

  1. can observe other values produced by Math.random in the target application, and
  2. can control one field of a request made using form-data

Because the values of Math.random() are pseudo-random and predictable (see: https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f), an attacker who can observe a few sequential values can determine the state of the PRNG and predict future values, includes those used to generate form-data's boundary value. The allows the attacker to craft a value that contains a boundary value, allowing them to inject additional parameters into the request.

This is largely the same vulnerability as was recently found in undici by parrot409 -- I'm not affiliated with that researcher but want to give credit where credit is due! My PoC is largely based on their work.

Details

The culprit is this line here: https://github.com/form-data/form-data/blob/426ba9ac440f95d1998dac9a5cd8d738043b048f/lib/form_data.js#L347

An attacker who is able to predict the output of Math.random() can predict this boundary value, and craft a payload that contains the boundary value, followed by another, fully attacker-controlled field. This is roughly equivalent to any sort of improper escaping vulnerability, with the caveat that the attacker must find a way to observe other Math.random() values generated by the application to solve for the state of the PRNG. However, Math.random() is used in all sorts of places that might be visible to an attacker (including by form-data itself, if the attacker can arrange for the vulnerable application to make a request to an attacker-controlled server using form-data, such as a user-controlled webhook -- the attacker could observe the boundary values from those requests to observe the Math.random() outputs). A common example would be a x-request-id header added by the server. These sorts of headers are often used for distributed tracing, to correlate errors across the frontend and backend. Math.random() is a fine place to get these sorts of IDs (in fact, opentelemetry uses Math.random for this purpose)

PoC

PoC here: https://github.com/benweissmann/CVE-2025-7783-poc

Instructions are in that repo. It's based on the PoC from https://hackerone.com/reports/2913312 but simplified somewhat; the vulnerable application has a more direct side-channel from which to observe Math.random() values (a separate endpoint that happens to include a randomly-generated request ID).

Impact

For an application to be vulnerable, it must:

  • Use form-data to send data including user-controlled data to some other system. The attacker must be able to do something malicious by adding extra parameters (that were not intended to be user-controlled) to this request. Depending on the target system's handling of repeated parameters, the attacker might be able to overwrite values in addition to appending values (some multipart form handlers deal with repeats by overwriting values instead of representing them as an array)
  • Reveal values of Math.random(). It's easiest if the attacker can observe multiple sequential values, but more complex math could recover the PRNG state to some degree of confidence with non-sequential values.

If an application is vulnerable, this allows an attacker to make arbitrary requests to internal systems.

critical: 0 high: 1 medium: 0 low: 0 linkifyjs 4.2.0 (npm)

pkg:npm/linkifyjs@4.2.0

high 8.8: CVE--2025--8101 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

Affected range<4.3.2
Fixed version4.3.2
CVSS Score8.8
CVSS VectorCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N
EPSS Score0.060%
EPSS Percentile19th percentile
Description

Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') vulnerability in Linkify (linkifyjs) allows XSS Targeting HTML Attributes and Manipulating User-Controlled Variables.This issue affects Linkify: from 4.3.1 before 4.3.2.

critical: 0 high: 1 medium: 0 low: 0 async 1.5.2 (npm)

pkg:npm/async@1.5.2

high 7.8: CVE--2021--43138 OWASP Top Ten 2017 Category A9 - Using Components with Known Vulnerabilities

Affected range<2.6.4
Fixed version2.6.4, 3.2.2
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.907%
EPSS Percentile75th percentile
Description

A vulnerability exists in Async through 3.2.1 (fixed in 3.2.2), which could let a malicious user obtain privileges via the mapValues() method.

critical: 0 high: 1 medium: 0 low: 0 async 0.9.2 (npm)

pkg:npm/async@0.9.2

high 7.8: CVE--2021--43138 OWASP Top Ten 2017 Category A9 - Using Components with Known Vulnerabilities

Affected range<2.6.4
Fixed version2.6.4, 3.2.2
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.907%
EPSS Percentile75th percentile
Description

A vulnerability exists in Async through 3.2.1 (fixed in 3.2.2), which could let a malicious user obtain privileges via the mapValues() method.

critical: 0 high: 1 medium: 0 low: 0 connect-multiparty 2.2.0 (npm)

pkg:npm/connect-multiparty@2.2.0

high 7.8: CVE--2022--29623 Unrestricted Upload of File with Dangerous Type

Affected range<=2.2.0
Fixed versionNot Fixed
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.320%
EPSS Percentile55th percentile
Description

An arbitrary file upload vulnerability in the file upload module of Express Connect-Multiparty 2.2.0 allows attackers to execute arbitrary code via a crafted PDF file. NOTE: the Supplier has not verified this vulnerability report.

Copy link
Contributor

@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: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 336cb19 and 8c211bc.

📒 Files selected for processing (1)
  • website/app.js (7 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: IhorMasechko
PR: speedandfunction/website#154
File: website/modules/case-studies-page/services/UrlService.js:102-116
Timestamp: 2025-06-09T16:52:54.510Z
Learning: When reviewing ApostropheCMS code, eslint-disable comments for `no-underscore-dangle` are often necessary and appropriate when accessing framework-provided properties like `_url`, as they conflict with general JavaScript linting rules but follow ApostropheCMS conventions.
📚 Learning: the project intentionally uses the `getenv` function for all environment variable access, including ...
Learnt from: killev
PR: speedandfunction/website#100
File: website/modules/@apostrophecms/form/index.js:227-227
Timestamp: 2025-05-19T20:40:04.914Z
Learning: The project intentionally uses the `getEnv` function for all environment variable access, including in placeholder values. This ensures that all required environment variables are present at application startup (fail-fast approach), even for features that might not be enabled.

Applied to files:

  • website/app.js
📚 Learning: when reviewing apostrophecms code, eslint-disable comments for `no-underscore-dangle` are often nece...
Learnt from: IhorMasechko
PR: speedandfunction/website#154
File: website/modules/case-studies-page/services/UrlService.js:102-116
Timestamp: 2025-06-09T16:52:54.510Z
Learning: When reviewing ApostropheCMS code, eslint-disable comments for `no-underscore-dangle` are often necessary and appropriate when accessing framework-provided properties like `_url`, as they conflict with general JavaScript linting rules but follow ApostropheCMS conventions.

Applied to files:

  • website/app.js
📚 Learning: in apostrophecms projects, even when a global page-type module removes the 'orphan' field, individua...
Learnt from: IhorMasechko
PR: speedandfunction/website#143
File: website/modules/default-page/index.js:24-24
Timestamp: 2025-06-02T16:04:13.069Z
Learning: In ApostropheCMS projects, even when a global page-type module removes the 'orphan' field, individual page modules (like default-page, home-page, case-studies-page) may still need explicit `remove: ['orphan']` for the removal to work correctly. The global improvement may not be sufficient in all cases.

Applied to files:

  • website/app.js
📚 Learning: applies to modules/@apostrophecms/form/index.js : modules/@apostrophecms/form/index.js: relaxed maxi...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to modules/@apostrophecms/form/index.js : modules/@apostrophecms/form/index.js: relaxed maximum lines rule

Applied to files:

  • website/app.js
📚 Learning: applies to modules/asset/ui/src/swipers.js : modules/asset/ui/src/swipers.js: relaxed import rules...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to modules/asset/ui/src/swipers.js : modules/asset/ui/src/swipers.js: relaxed import rules

Applied to files:

  • website/app.js
📚 Learning: applies to modules/asset/ui/src/index.js : modules/asset/ui/src/index.js: relaxed function lines and...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to modules/asset/ui/src/index.js : modules/asset/ui/src/index.js: relaxed function lines and style rules

Applied to files:

  • website/app.js
📚 Learning: applies to **/*.{js,jsx} : no duplicate object keys...
Learnt from: CR
PR: speedandfunction/website#0
File: .cursor/rules/code-conventions.mdc:0-0
Timestamp: 2025-07-01T07:44:33.034Z
Learning: Applies to **/*.{js,jsx} : No duplicate object keys

Applied to files:

  • website/app.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e-tests
  • GitHub Check: security-scan
  • GitHub Check: lint
  • GitHub Check: unit-tests
🔇 Additional comments (3)
website/app.js (3)

30-37: LGTM! Proper session cookie configuration for production

The session cookie configuration correctly addresses the CSRF issue by:

  • Setting the domain with a leading dot (.speedandfunction.com) to ensure cookies work across subdomains
  • Enabling secure flag for HTTPS-only transmission in production
  • Using sameSite: 'lax' which allows the cookie to be sent with top-level navigations (necessary for login)
  • Setting appropriate security flags (httpOnly: true)

18-19: LGTM! Essential for proxy deployments

Enabling trustProxy is correct and necessary for Railway deployments or any deployment behind a reverse proxy. This ensures Express properly interprets X-Forwarded-* headers for client IP and protocol detection.


48-49: Good documentation of critical fix

The comment clearly identifies this as the critical fix for the CSRF issue with custom domains. This helps future maintainers understand the importance of this configuration.

website/app.js Outdated
Comment on lines 6 to 7
const isProduction = process.env.NODE_ENV === 'production';
const baseUrl = getEnv('BASE_URL') || (isProduction ? 'https://speedandfunction.com' : 'http://localhost:3000');
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider fail-fast approach for BASE_URL environment variable

The current implementation uses getEnv('BASE_URL') || ... which provides a fallback, but this contradicts the project's fail-fast approach for required environment variables (as mentioned in the learnings). If BASE_URL is a required configuration, consider:

-  const baseUrl = getEnv('BASE_URL') || (isProduction ? 'https://speedandfunction.com' : 'http://localhost:3000');
+  const baseUrl = getEnv('BASE_URL', isProduction ? 'https://speedandfunction.com' : 'http://localhost:3000');

Or if BASE_URL should be optional:

-  const baseUrl = getEnv('BASE_URL') || (isProduction ? 'https://speedandfunction.com' : 'http://localhost:3000');
+  const baseUrl = process.env.BASE_URL || (isProduction ? 'https://speedandfunction.com' : 'http://localhost:3000');

Let me verify the getEnv function signature to understand if it supports default values:


🏁 Script executed:

#!/bin/bash
# Search for the getEnv function definition
rg -A 10 "function getEnv|const getEnv|exports\.getEnv" website/utils/env.js

Length of output: 295


Fix unreachable fallback due to getEnv signature

The helper getEnv(name) only accepts a single argument and throws if the variable is undefined, so

getEnv('BASE_URL') || 

will never fall back. To provide a default you must use process.env for optional variables or split logic:

• If BASE_URL is optional (with a built-in fallback for all environments):

--- a/website/app.js
+++ b/website/app.js
@@ (around line 6)
-  const baseUrl = getEnv('BASE_URL') || (isProduction
-    ? 'https://speedandfunction.com'
-    : 'http://localhost:3000');
+  const baseUrl = process.env.BASE_URL
+    || (isProduction
+      ? 'https://speedandfunction.com'
+      : 'http://localhost:3000');

• If you want to fail-fast in production but allow a dev fallback:

--- a/website/app.js
+++ b/website/app.js
@@ (around line 6)
-  const baseUrl = getEnv('BASE_URL') || (isProduction
-    ? 'https://speedandfunction.com'
-    : 'http://localhost:3000');
+  const baseUrl = isProduction
+    ? getEnv('BASE_URL')                  // will throw if unset
+    : (process.env.BASE_URL || 'http://localhost:3000');

Please update lines 6–7 in website/app.js accordingly so fallbacks behave as intended.

🤖 Prompt for AI Agents
In website/app.js around lines 6 to 7, the current use of getEnv('BASE_URL')
prevents fallback because getEnv throws if the variable is undefined. To fix
this, replace getEnv('BASE_URL') with process.env.BASE_URL to allow optional
fallback, or restructure the logic to call getEnv only in production for
fail-fast behavior and use a fallback for development. Adjust the assignment of
baseUrl accordingly to ensure the fallback URL is reachable as intended.

website/app.js Outdated
Comment on lines 53 to 59
value: (req) => {
return req.body && req.body._csrf ||
req.query && req.query._csrf ||
req.headers['x-csrf-token'] ||
req.headers['x-xsrf-token'] ||
req.headers['csrf-token'];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential issue in CSRF token extraction logic

The current implementation might return falsy values (empty string, 0) instead of checking all possible locations. Consider using nullish coalescing or explicit checks:

-            value: (req) => {
-              return req.body && req.body._csrf ||
-                     req.query && req.query._csrf ||
-                     req.headers['x-csrf-token'] ||
-                     req.headers['x-xsrf-token'] ||
-                     req.headers['csrf-token'];
-            }
+            value: (req) => {
+              return req.body?._csrf ||
+                     req.query?._csrf ||
+                     req.headers['x-csrf-token'] ||
+                     req.headers['x-xsrf-token'] ||
+                     req.headers['csrf-token'];
+            }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In website/app.js around lines 53 to 59, the CSRF token extraction logic uses ||
which can return falsy values like empty strings or 0 prematurely. Replace the
|| operators with nullish coalescing operators (??) or add explicit checks to
ensure that only null or undefined values cause fallback to the next location,
so all possible token sources are properly checked.

website/app.js Outdated
Comment on lines 68 to 77
if (req.hostname === 'speedandfunction.com' || req.get('host') === 'speedandfunction.com') {
req.headers['x-forwarded-host'] = 'speedandfunction.com';
req.headers['x-forwarded-proto'] = 'https';
}

// Set CORS headers for API requests
const allowedOrigins = [
'https://speedandfunction.com',
'https://apostrophe-cms-production.up.railway.app'
];
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider making domain and CORS origins configurable

The hardcoded domains and allowed origins reduce maintainability. Consider using environment variables:

-                if (req.hostname === 'speedandfunction.com' || req.get('host') === 'speedandfunction.com') {
-                  req.headers['x-forwarded-host'] = 'speedandfunction.com';
+                const customDomain = process.env.CUSTOM_DOMAIN || 'speedandfunction.com';
+                if (req.hostname === customDomain || req.get('host') === customDomain) {
+                  req.headers['x-forwarded-host'] = customDomain;
                   req.headers['x-forwarded-proto'] = 'https';
                 }
                 
                 // Set CORS headers for API requests
-                const allowedOrigins = [
-                  'https://speedandfunction.com',
-                  'https://apostrophe-cms-production.up.railway.app'
-                ];
+                const allowedOrigins = (process.env.ALLOWED_ORIGINS || 'https://speedandfunction.com,https://apostrophe-cms-production.up.railway.app').split(',');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (req.hostname === 'speedandfunction.com' || req.get('host') === 'speedandfunction.com') {
req.headers['x-forwarded-host'] = 'speedandfunction.com';
req.headers['x-forwarded-proto'] = 'https';
}
// Set CORS headers for API requests
const allowedOrigins = [
'https://speedandfunction.com',
'https://apostrophe-cms-production.up.railway.app'
];
const customDomain = process.env.CUSTOM_DOMAIN || 'speedandfunction.com';
if (req.hostname === customDomain || req.get('host') === customDomain) {
req.headers['x-forwarded-host'] = customDomain;
req.headers['x-forwarded-proto'] = 'https';
}
// Set CORS headers for API requests
const allowedOrigins = (process.env.ALLOWED_ORIGINS || 'https://speedandfunction.com,https://apostrophe-cms-production.up.railway.app').split(',');
🤖 Prompt for AI Agents
In website/app.js around lines 68 to 77, the domain and CORS allowed origins are
hardcoded, which reduces maintainability. Refactor the code to read these values
from environment variables instead of hardcoding them. Update the hostname
checks and the allowedOrigins array to use environment variables, providing
sensible defaults if needed, so the domains can be easily changed without
modifying the source code.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 5, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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