Skip to content

fix: harden CSRF protections - #6186

Merged
alespour merged 20 commits into
masterfrom
fix/issue-1041
Mar 31, 2026
Merged

fix: harden CSRF protections#6186
alespour merged 20 commits into
masterfrom
fix/issue-1041

Conversation

@alespour

@alespour alespour commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

CSRF hardening fixes:

  • Data Explorer no longer executes queries from URL parameters (?query= / ?script=) on page load. This directly addresses the issue recommendation to disable URL-based query execution (or at least stop auto-execution). It removes the crafted-link CSRF vector described in CSA-H-04.
  • Session cookie settings were hardened. Cookies now use stricter cross-site behavior (SameSite=Strict) and secure transport settings where appropriate. This reduces the chance that browser session cookies are sent on cross-origin requests.
  • Query execution/proxy endpoints now require X-Requested-With: XMLHttpRequest. This follows the issue proposal to require an AJAX-only header so cross-origin pages cannot trigger those requests directly. Requests without that header are rejected.

Fixes beyond CSA-H-04 recommendations:

  • Same-origin validation was added for unsafe, session-authenticated requests. For POST/PUT/PATCH/DELETE, requests must present valid same-origin context (Origin or Referer) or they are blocked. This adds a server-side CSRF barrier aligned with the issue’s same-origin recommendation.
  • Defense-in-depth response headers were added. X-Frame-Options: SAMEORIGIN and Cross-Origin-Resource-Policy: same-origin are now set. This reduces framing and cross-origin resource abuse opportunities.

Tests to do

  • Verify login works and session persists after refresh.
  • Verify logout clears session and returns to login.
  • Open /sources/:id/chronograf/data-explorer directly and confirm page loads normally.
  • Open with ?query=... and ?script=...; confirm text may appear but query does not auto-run.
  • In InfluxQL tab, run a basic query (for example SHOW DATABASES) and confirm results render.
  • In Flux tab, run a safe query (for example buckets()) and confirm results render.
  • Perform actions that send POST/PUT/DELETE (create DB, drop DB, save dashboard cell, update source config).
  • Confirm no unexpected 403 errors in browser Network tab.
  • Confirm app works when accessed the same way as production (through proxy/LB host).
  • If behind TLS terminator, verify cookies include Secure and app still authenticates.
  • Check for failed XHR/fetch requests to /chronograf/v1/*.

@alespour alespour changed the title Fix/issue 1041 fix: security 1401 Mar 17, 2026
@alespour alespour changed the title fix: security 1401 fix: CSRF security Mar 17, 2026
@alespour alespour changed the title fix: CSRF security fix: CSRF issues Mar 17, 2026
@alespour
alespour marked this pull request as ready for review March 18, 2026 07:01
@alespour alespour changed the title fix: CSRF issues fix: CSRF hardening Mar 18, 2026
@alespour alespour changed the title fix: CSRF hardening fix: hardened CSRF protections Mar 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This pull request hardens Chronograf’s CSRF posture and adds additional browser isolation measures by introducing server-side request guards (Origin/Referer validation for session-auth unsafe methods, and required X-Requested-With on sensitive endpoints) and updating UI/Cypress clients to comply.

Changes:

  • Add server middleware for same-origin enforcement (session-cookie + unsafe methods), required X-Requested-With: XMLHttpRequest on query/proxy endpoints, and default security headers.
  • Update UI worker/fetch/XHR callers to send X-Requested-With, and update Cypress cy.request to inject Origin/Referer for unsafe same-origin API calls.
  • Tighten session cookie attributes (SameSite=Strict and conditional Secure) and remove Data Explorer query param syncing logic.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ui/src/worker/jobs/proxy.ts Adds X-Requested-With to proxy POST fetches.
ui/src/worker/jobs/postJSON.ts Adds X-Requested-With to JSON POST fetches.
ui/src/utils/ajax.ts Injects X-Requested-With into non-GET requests and /proxy/flux GET.
ui/src/shared/apis/flux/query.ts Adds X-Requested-With to Flux XHR execution.
ui/src/shared/apis/flux/cancellableQuery.ts Adds X-Requested-With to Flux cancellable fetch.
ui/src/data_explorer/containers/DataExplorer.tsx Removes URL query/script param read/write behavior.
ui/cypress/support/commands.ts Overwrites cy.request to inject Origin/Referer for unsafe same-origin calls.
ui/cypress/integration/explore_influxql.test.ts Makes the test resilient to non-deterministic DB names from templates.
server/server.go Passes TLS-derived “secure cookie” flag into cookie JWT auth.
server/security_headers.go Adds middleware to set XFO + CORP headers.
server/same_origin.go Adds middleware to require same-origin Origin/Referer for unsafe session-cookie requests.
server/requested_with.go Adds middleware requiring X-Requested-With: XMLHttpRequest.
server/mux.go Wires new middleware into mux and protects query/proxy endpoints.
server/middle_test.go Adds tests for the new middleware behaviors.
oauth2/cookies.go Adds SameSite=Strict + Secure support to session cookies.
oauth2/cookies_test.go Updates tests for new NewCookieJWT signature.
CHANGELOG.md Documents the security hardening under Unreleased.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui/src/utils/ajax.ts Outdated
Comment thread server/same_origin.go Outdated
Comment thread server/mux.go Outdated
Comment thread server/middle_test.go Outdated
alespour and others added 4 commits March 18, 2026 08:59
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens Chronograf’s browser-facing security posture by adding CSRF defenses on unsafe endpoints, tightening session-cookie attributes, and updating UI/Cypress callers to send the required request headers.

Changes:

  • Enforce X-Requested-With: XMLHttpRequest on selected query/proxy endpoints and add a same-origin check for unsafe methods when session cookies are present.
  • Add defense-in-depth security response headers and strengthen session cookie attributes (SameSite, optional Secure).
  • Update UI worker/Flux clients and Cypress tests to include X-Requested-With (and inject Origin/Referer in Cypress), plus adjust a flaky InfluxQL e2e assertion.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ui/src/worker/jobs/proxy.ts Adds X-Requested-With (+ JSON content type) to proxy worker POSTs.
ui/src/worker/jobs/postJSON.ts Adds X-Requested-With to JSON POST worker requests.
ui/src/utils/ajax.ts Injects X-Requested-With for non-GET and /proxy/flux GET requests.
ui/src/shared/apis/flux/query.ts Adds X-Requested-With header to Flux XHR POST.
ui/src/shared/apis/flux/cancellableQuery.ts Adds X-Requested-With to cancellable Flux fetch headers.
ui/src/data_explorer/containers/DataExplorer.tsx Removes query-param read/write logic (and related imports).
ui/cypress/support/commands.ts Overwrites cy.request to inject Origin/Referer for same-origin unsafe methods.
ui/cypress/integration/explore_influxql.test.ts Makes metaquery template test resilient by extracting created DB name dynamically.
server/server.go Passes a new secure flag into cookie auth creation.
server/security_headers.go Adds middleware to set X-Frame-Options and Cross-Origin-Resource-Policy.
server/same_origin.go Adds middleware to block cross-origin unsafe requests when session cookie is present.
server/requested_with.go Adds middleware to require X-Requested-With: XMLHttpRequest.
server/mux.go Applies new guards to proxy/queries routes and wires global security middleware.
server/middle_test.go Adds unit tests for the new middleware behaviors.
oauth2/cookies.go Adds Secure + SameSite=Strict to session cookies and updates constructor signature.
oauth2/cookies_test.go Updates tests for the new cookie constructor signature.
CHANGELOG.md Notes the security hardening under “Unreleased”.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/server.go Outdated
Comment thread ui/src/data_explorer/containers/DataExplorer.tsx Outdated
@karel-rehor
karel-rehor self-requested a review March 19, 2026 13:37
@alespour alespour changed the title fix: hardened CSRF protections fix: harden CSRF protections Mar 19, 2026
@karel-rehor

Copy link
Copy Markdown
Contributor

I've gone through the check list of tests in the description and repeated them against a local build of this branch built in a cross builder container. So this is more or less what will be built in CI. Note there is currently an issue with nightly builds in CI due to missing compilers for darwin. The local build was for linux amd64 only.

INFO[0000] Starting Chronograf 1.11.0ea3e1c64bece6ccd8295ed494130f0816f4fa6f7 

An application was created in my Github account to use OAuth2 configuration.

screenshot of initial oauth2 configuration

This configuration is for the plain HTTP envoy proxy at localhost:10000

Screenshot from 2026-03-25 17-27-14

Everything appears to work as could be expected...

Verification test run notes

  • Verify login works and session persists after refresh.

With Github OAuth2 - OK

  • Verify logout clears session and returns to login.

With Github OAuth2 - OK

session cookie cleared on logout, new session cookie on login

first session cookie... eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzQ0NDQzMzIsImlhdCI6MTc3NDQ0MzM2MSwiaXNzIjoiZ2l0aHViIiwibmJmIjoxNzc0NDQzMzYxLCJzdWIiOiJrYXJsLmtvZXJuZXJAYm9uaXRvby5pbyIsImdycCI6ImJvbml0b28taW8ifQ.pRI3xAEdYfFO5tpz8z0kLl5_FVOyh0G9vtw7UC0djBs

second session cookie...
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzQ0NDQ0MDgsImlhdCI6MTc3NDQ0NDEwOCwiaXNzIjoiZ2l0aHViIiwibmJmIjoxNzc0NDQ0MTA4LCJzdWIiOiJrYXJsLmtvZXJuZXJAYm9uaXRvby5pbyIsImdycCI6ImJvbml0b28taW8ifQ.7DqngtTTffJM1CY1y7V5P9zzUhm2ATC2ZxWAMRGSXZI

  • Open /sources/:id/chronograf/data-explorer directly and confirm page loads normally.

With Github OAuth2 - OK

  • Open with ?query=... and ?script=...; confirm text may appear but query does not auto-run.

query? parameter does not load - OK
script? paramete does not load - OK

  • In InfluxQL tab, run a basic query (for example SHOW DATABASES) and confirm results render.

Rendered - OK

  • In Flux tab, run a safe query (for example buckets()) and confirm results render.

Rendered - OK

  • Perform actions that send POST/PUT/DELETE (create DB, drop DB, save dashboard cell, update source config).

POST - OK
most queries, etc.
PUT - OK
Rename dashboard
DELETE - OK
Delete dashboard

  • Confirm no unexpected 403 errors in browser Network tab.

None encountered - OK
Expected 403 on http://localhost:10888/chronograf/v1/me - immediately after logout...

  • Confirm app works when accessed the same way as production (through proxy/LB host).

With HTTP Envoy proxy - OK

  • If behind TLS terminator, verify cookies include Secure and app still authenticates.

    • Used self-signed certs with envoy and Github Oauth2 - OK
    • Session cookies updated with logout/login
    • app still authenticates and works
      • explorer
      • create dashboard cell
      • delete dashboard cell
  • Check for failed XHR/fetch requests to /chronograf/v1/*.

None detected - OK

@karel-rehor karel-rehor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review in progress. One question on unit tests.

Comment thread oauth2/cookies_test.go

@karel-rehor karel-rehor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me 🚴 🏁

@alespour
alespour merged commit d93e9de into master Mar 31, 2026
3 of 4 checks passed
@alespour
alespour deleted the fix/issue-1041 branch March 31, 2026 07:03
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