Skip to content

[security] fix(auth): reject cross-site auth POSTs#2740

Merged
WillemJiang merged 3 commits intobytedance:mainfrom
Hinotoi-agent:fix/auth-origin-csrf
May 6, 2026
Merged

[security] fix(auth): reject cross-site auth POSTs#2740
WillemJiang merged 3 commits intobytedance:mainfrom
Hinotoi-agent:fix/auth-origin-csrf

Conversation

@Hinotoi-agent
Copy link
Copy Markdown
Contributor

Summary

This PR hardens the browser authentication boundary around CSRF-exempt auth endpoints.

Auth routes such as /api/v1/auth/login/local intentionally skip the double-submit CSRF token because first-time browser clients do not have a CSRF cookie yet. Before this change, those same endpoints also accepted browser POSTs with a hostile Origin, which allowed login CSRF/session fixation: a malicious site could submit the victim browser to DeerFlow with attacker-controlled credentials and cause later victim activity to be saved under the attacker account.

This PR:

  • rejects CSRF-exempt auth POSTs when the browser Origin is neither same-origin nor explicitly configured in GATEWAY_CORS_ORIGINS;
  • preserves same-origin auth, explicitly configured dev/CORS origins, and no-Origin non-browser clients;
  • keeps the existing double-submit CSRF behavior unchanged for ordinary state-changing API routes;
  • adds focused middleware regression tests for hostile origins, forwarded proxy headers, malformed origins, CORS-origin compatibility, and double-submit behavior.

Security issues covered

Issue Impact Severity
Login CSRF / session fixation on CSRF-exempt auth POSTs A hostile site can force a victim browser into an attacker-controlled account; later prompts, uploads, memories, and generated artifacts may be associated with that attacker-visible account Medium

Before this PR

  • /api/v1/auth/login/local, /register, /initialize, and /logout were exempt from CSRF token validation.
  • /api/v1/auth/login/local accepts browser-form-postable credentials through OAuth2PasswordRequestForm.
  • A cross-site form POST could reach the auth endpoint without CORS or a CSRF token.
  • A successful auth response could set DeerFlow session cookies in the victim browser.
  • There were no regression tests covering hostile Origin handling on CSRF-exempt auth routes.

After this PR

  • CSRF-exempt auth POSTs now reject hostile browser origins with 403.
  • Same-origin browser login/register/setup flows continue to work.
  • Explicitly configured GATEWAY_CORS_ORIGINS continue to work for split frontend/backend deployments.
  • Requests without an Origin header continue to work for non-browser clients such as curl/mobile integrations.
  • Existing double-submit CSRF checks for non-auth mutations are unchanged and covered by tests.

Why this matters

Cookie SameSite=Lax does not prevent a top-level cross-site form POST from causing the target site to set cookies on the response. Because login is a session-creating endpoint, a malicious page can submit attacker-known DeerFlow credentials and silently switch the victim browser into the attacker account.

The attacker does not steal the victim's existing DeerFlow account. The risk is session confusion and data capture: after the forced login, the victim may enter prompts, upload files, or generate artifacts that the attacker can later access by logging into the same attacker-controlled account.

Attack flow

Hostile web page with auto-submitting login form
    -> POST /api/v1/auth/login/local with attacker credentials
        -> CSRF-exempt auth route accepts hostile browser Origin
            -> DeerFlow sets session cookies for the attacker account in the victim browser
                -> Later victim activity is stored under attacker-visible account state

Affected code

Issue Files
Login CSRF / session fixation backend/app/gateway/csrf_middleware.py, backend/app/gateway/routers/auth.py

Root cause

Issue: login CSRF / session fixation

  • The auth endpoints were correctly exempted from double-submit CSRF for first-call usability, but there was no compensating browser-origin check.
  • The login endpoint accepts standard form encoding, so a hostile site can trigger it with a top-level HTML form POST without needing CORS access.

CVSS assessment

Issue CVSS v3.1 Vector
Login CSRF / session fixation 6.5 Medium CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

Rationale:

  • Network-reachable web attack requiring victim interaction with a hostile page.
  • No DeerFlow privileges are required for the attacker beyond having or creating an attacker-controlled account on the target instance.
  • The primary impact is confidentiality of victim-entered prompts/uploads/artifacts after the forced login; this PR does not claim direct victim account takeover.

Safe reproduction steps

  1. On vulnerable code, host this minimal page on another origin:

    <!doctype html>
    <form action="https://deerflow.example/api/v1/auth/login/local" method="POST">
      <input name="username" value="attacker@example.com">
      <input name="password" value="attacker-known-password">
    </form>
    <script>document.forms[0].submit()</script>
  2. Have a victim browser visit the page.

  3. The browser submits a cross-site form POST to DeerFlow.

  4. On vulnerable code, the auth route processes the request because it is CSRF-exempt.

  5. The victim browser receives DeerFlow auth cookies for the attacker account.

  6. Any later work the victim performs in DeerFlow is associated with that attacker account.

The regression test test_auth_post_rejects_cross_origin_browser_request captures the safe proof without requiring real credentials.

Expected vulnerable behavior

  • Cross-origin browser POSTs to /api/v1/auth/login/local were accepted.
  • The middleware generated a CSRF cookie after the auth POST rather than rejecting the hostile origin.
  • No test failed for hostile browser origins on auth endpoints.

Changes in this PR

  • Adds strict Origin normalization for scheme, host, and non-default port.
  • Rejects malformed browser Origin values such as URL-shaped origins with paths or invalid ports.
  • Computes the request origin using direct host headers plus X-Forwarded-* and RFC 7239 Forwarded proxy headers.
  • Allows same-origin auth POSTs and explicit GATEWAY_CORS_ORIGINS entries.
  • Ignores wildcard CORS (*) for auth-origin bypass purposes.
  • Preserves no-Origin behavior for non-browser clients.
  • Adds focused CSRF middleware regression coverage.

Files changed

Category Files What changed
Middleware backend/app/gateway/csrf_middleware.py Added auth-origin validation helpers and a 403 rejection path for hostile auth POST origins
Tests backend/tests/test_csrf_middleware.py Added regression tests for hostile origins, same-origin/default-port matching, forwarded proxy headers, configured origins, wildcard rejection, no-Origin clients, and double-submit CSRF behavior

Maintainer impact

  • The patch is limited to CSRF middleware and focused tests.
  • It does not change auth provider logic, JWT creation, password validation, frontend routes, or non-auth CSRF semantics.
  • Same-origin deployments keep the existing behavior.
  • Split frontend/backend deployments can continue to use explicit GATEWAY_CORS_ORIGINS.
  • Non-browser clients that do not send Origin remain compatible.

Suggested fix rationale

Origin checking is the appropriate compensating control for session-creating endpoints that cannot require a pre-existing CSRF token. It blocks browser-driven cross-site login/register/setup requests while avoiding a bootstrap problem for legitimate first-time auth flows.

The helper fails closed for malformed browser Origin values, handles common reverse-proxy headers, and keeps ordinary double-submit checks unchanged for all other state-changing routes.

Type of change

  • Security fix
  • Tests
  • Documentation update
  • Refactor with no behavior change

Test plan

  • Auth-origin regression tests pass.
  • Existing auth/auth-middleware tests pass.
  • Ruff check passes for touched files.
  • Ruff format check passes for touched files.
  • Python compile check passes for touched files.
  • Git whitespace check passes.

Executed with:

cd backend
uv run pytest -q tests/test_csrf_middleware.py tests/test_auth_middleware.py tests/test_auth.py
uv run ruff check app/gateway/csrf_middleware.py tests/test_csrf_middleware.py
uv run ruff format --check app/gateway/csrf_middleware.py tests/test_csrf_middleware.py
uv run python -m compileall -q app/gateway/csrf_middleware.py tests/test_csrf_middleware.py
git diff --check

Result:

  • 111 passed, 1 warning for the targeted pytest command.
  • Ruff, format check, compile check, and git diff --check passed.
  • The remaining warning is from an existing test_auth_middleware.py cookie-use deprecation and is unrelated to this patch.

Token usage

  • discovery tokens: partial/unknown
  • validation tokens: partial/unknown
  • duplicate-check tokens: partial/unknown
  • PR/writeup tokens: partial/unknown
  • total tokens: partial/unknown
  • notes: This PR came from an interactive security review with delegated review passes; exact end-to-end token accounting is not available from the local tool output.

Disclosure notes

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 DeerFlow’s CSRF-exempt auth endpoints (login/register/logout/initialize) by adding an Origin-based browser boundary check, preventing cross-site form POSTs from creating attacker-controlled sessions (login CSRF / session fixation), while preserving same-origin behavior and explicitly configured CORS origins.

Changes:

  • Added origin normalization + proxy-aware request-origin reconstruction (including X-Forwarded-* and RFC 7239 Forwarded) and enforced 403 for hostile/malformed browser Origin values on CSRF-exempt auth POSTs.
  • Preserved existing double-submit CSRF enforcement for non-auth state-changing routes.
  • Added focused regression tests covering hostile origins, malformed origins, forwarded proxy headers, explicit CORS origins, wildcard handling, and double-submit behavior.

Reviewed changes

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

File Description
backend/app/gateway/csrf_middleware.py Adds origin parsing/normalization and rejects cross-site browser Origins for CSRF-exempt auth POST endpoints.
backend/tests/test_csrf_middleware.py Adds regression tests for the new auth-origin restriction and confirms non-auth CSRF behavior remains enforced.

Comment thread backend/app/gateway/csrf_middleware.py
Comment thread backend/tests/test_csrf_middleware.py
@WillemJiang WillemJiang added this to the 2.0-m1 milestone May 6, 2026
@WillemJiang WillemJiang merged commit 2b0e62f into bytedance:main May 6, 2026
5 checks passed
Wingxxx pushed a commit to Wingxxx/deer-flow that referenced this pull request May 7, 2026
* fix(security): reject cross-site auth posts

* fix(auth): align secure cookie proxy scheme handling

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
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