mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-05-23 08:25:57 +00:00
security(auth): strict JWT validation in middleware (fix junk cookie bypass)
AUTH_TEST_PLAN test 7.5.8 expects junk cookies to be rejected with 401. The previous middleware behaviour was "presence-only": check that some access_token cookie exists, then pass through. In combination with my Task-12 decision to skip @require_auth decorators on routes, this created a gap where a request with any cookie-shaped string (e.g. access_token=not-a-jwt) would bypass authentication on routes that do not touch the repository (/api/models, /api/mcp/config, /api/memory, /api/skills, …). Fix: middleware now calls get_current_user_from_request() strictly and catches the resulting HTTPException to render a 401 with the proper fine-grained error code (token_invalid, token_expired, user_not_found, …). On success it stamps request.state.user and the contextvar so repository-layer owner filters work downstream. The 4 old "_with_cookie_passes" tests in test_auth_middleware.py were written for the presence-only behaviour; they asserted that a junk cookie would make the handler return 200. They are renamed to "_with_junk_cookie_rejected" and their assertions flipped to 401. The negative path (no cookie → 401 not_authenticated) is unchanged. Verified: no cookie → 401 not_authenticated junk cookie → 401 token_invalid (the fixed bug) expired cookie → 401 token_expired Tests: 284 passed (auth + persistence + isolation) Lint: clean
This commit is contained in:
@@ -161,9 +161,12 @@ def test_protected_path_no_cookie_returns_401(client):
|
||||
assert body["detail"]["code"] == "not_authenticated"
|
||||
|
||||
|
||||
def test_protected_path_with_cookie_passes(client):
|
||||
def test_protected_path_with_junk_cookie_rejected(client):
|
||||
"""Junk cookie → 401. Middleware strictly validates the JWT now
|
||||
(AUTH_TEST_PLAN test 7.5.8); it no longer silently passes bad
|
||||
tokens through to the route handler."""
|
||||
res = client.get("/api/models", cookies={"access_token": "some-token"})
|
||||
assert res.status_code == 200
|
||||
assert res.status_code == 401
|
||||
|
||||
|
||||
def test_protected_post_no_cookie_returns_401(client):
|
||||
@@ -189,16 +192,18 @@ def test_protected_patch_no_cookie(client):
|
||||
assert res.status_code == 401
|
||||
|
||||
|
||||
def test_put_with_cookie_passes(client):
|
||||
def test_put_with_junk_cookie_rejected(client):
|
||||
"""Junk cookie on PUT → 401 (strict JWT validation in middleware)."""
|
||||
client.cookies.set("access_token", "tok")
|
||||
res = client.put("/api/mcp/config")
|
||||
assert res.status_code == 200
|
||||
assert res.status_code == 401
|
||||
|
||||
|
||||
def test_delete_with_cookie_passes(client):
|
||||
def test_delete_with_junk_cookie_rejected(client):
|
||||
"""Junk cookie on DELETE → 401 (strict JWT validation in middleware)."""
|
||||
client.cookies.set("access_token", "tok")
|
||||
res = client.delete("/api/threads/abc")
|
||||
assert res.status_code == 200
|
||||
assert res.status_code == 401
|
||||
|
||||
|
||||
# ── Fail-closed: unknown future endpoints ─────────────────────────────────
|
||||
@@ -210,7 +215,8 @@ def test_unknown_endpoint_no_cookie_returns_401(client):
|
||||
assert res.status_code == 401
|
||||
|
||||
|
||||
def test_unknown_endpoint_with_cookie_passes(client):
|
||||
def test_unknown_endpoint_with_junk_cookie_rejected(client):
|
||||
"""New endpoints are also protected by strict JWT validation."""
|
||||
client.cookies.set("access_token", "tok")
|
||||
res = client.get("/api/future-endpoint")
|
||||
assert res.status_code == 200
|
||||
assert res.status_code == 401
|
||||
|
||||
Reference in New Issue
Block a user