fix: A19 terminé — plus aucun préfixe cookie-auth exempt du CSRF (v7.3.6)
FlowDeck CI / test (push) Successful in 20m10s
FlowDeck CI / lint (push) Successful in 1m51s
FlowDeck CI / docker (push) Canceled after 0s

- 46 appels non-GET équipés de `X-CSRF-Token` (expression cookie en ligne,
  portée indifférente) : agent_panel (9), settings (12), local_workspace (15),
  gitea_workspace (4), workspace (2), workspaces (5), library (2), welcome (2 en v7.3.5)
- 5 derniers préfixes sortis d'`EXCLUDED_PATHS` : /api/workspace (+/api/workspaces),
  /api/local-workspace, /api/settings, /api/gitea, /api/agent
- il ne reste exempté que : Bearer (/api/webhook, /api/v1, /api/v2, /scim/v2),
  callbacks /auth/*, pages publiques (/s/, /f/), /api/csrf-token et /api/frontend-error
- vérif : `node --check` des <script> des 39 templates → 0 échec (avant et après)
- tests : `anon_csrf()` sur les 5 tests d'anonymat devenus CSRF-first
- suite **1026/1026** · `ruff check app tests` OK
This commit is contained in:
2026-10-01 07:41:23 -04:00
parent cf76e00f12
commit 1f705ce512
16 changed files with 87 additions and 69 deletions
+3 -3
View File
@@ -4,7 +4,7 @@ import os
import tempfile
import pytest
from conftest import anon, login_test_client
from conftest import anon, anon_csrf, login_test_client
from fastapi.testclient import TestClient
@@ -1670,7 +1670,7 @@ def test_gitea_status_with_expired_token(client):
def test_gitea_disconnect_no_auth(client):
anon(client)
anon_csrf(client)
"""DELETE /api/gitea/disconnect — 401 without session."""
resp = client.delete("/api/gitea/disconnect")
assert resp.status_code == 401
@@ -1952,7 +1952,7 @@ def test_gitea_private_pages_list_no_auth(client):
def test_gitea_private_pages_create_no_auth(client):
anon(client)
anon_csrf(client)
"""POST private-pages — 401 without session."""
resp = client.post("/api/gitea/projects/owner/repo/private-pages", json={"title": "Test"})
assert resp.status_code == 401
+1 -1
View File
@@ -96,7 +96,7 @@ def test_upload_requires_session_and_validates_files(client):
assert validate_upload("virus.exe", 10) is not None
assert validate_upload("big.txt", 11 * 1024 * 1024) is not None
anon(client)
anon_csrf(client)
r = client.post("/api/local-workspace/upload", files={"files": ("a.txt", b"x", "text/plain")})
assert r.status_code == 401
+6 -3
View File
@@ -8,7 +8,7 @@ import asyncio
import os
import pytest
from conftest import anon
from conftest import anon_csrf
from fastapi import HTTPException
from fastapi.testclient import TestClient
@@ -67,7 +67,7 @@ def test_api_token_lifecycle(client):
def test_api_tokens_require_authentication(client):
anon(client)
anon_csrf(client)
r1 = client.get("/api/settings/tokens")
assert r1.status_code == 401
r2 = client.post("/api/settings/tokens", json={"name": "x"})
@@ -106,6 +106,9 @@ def test_sessions_listed_and_revocable(client):
# Create a fresh client with alice's cookie to revoke.
client_alice = TestClient(client.app)
client_alice.cookies.set("flowdeck_session", alice_cookie)
# CSRF aussi sur ce client jetable (la route n'est plus exemptée, A19).
client_alice.cookies.set("csrf_token", "csrf-alice")
client_alice.headers["X-CSRF-Token"] = "csrf-alice"
revoke = client_alice.post(f"/api/settings/sessions/{alice_sid}/revoke")
assert revoke.status_code == 200
@@ -198,7 +201,7 @@ def test_backup_disabled_returns_none(client):
def test_backup_admin_api(client):
anon(client)
anon_csrf(client)
"""The backup admin API is admin-only and snapshots on demand."""
# Unauthenticated → forbidden.
assert client.post("/api/settings/backups/run").status_code == 403