fix: A19 (partiel) — CSRF réservé aux vrais cas d'exemption (v7.3.5)
- Scan de tous les appels `fetch` non-GET du front par préfixe : 12 préfixes n'ont AUCUN call site sans `X-CSRF-Token` → sortis de `EXCLUDED_PATHS` (`/db/`, `/workspace`, `/workspace/automations`, `/board/api/favorites`, `/api/pages`, `/api/recents`, `/api/notifications`, `/api/comments`, `/api/automations`, `/api/github`, `/api/admin`, `/api/onboarding`) - `welcome.html` : les 2 POST `/api/onboarding/*` reçoivent le header (`adminFetch` prouve que `/api/admin` était déjà couvert) - reste A19 (front à équiper) : `/api/workspace` (+`/api/workspaces`), `/api/local-workspace`, `/api/settings`, `/api/gitea`, `/api/agent` — 49 fetch - tests : helper `anon_csrf()` (anonyme + CSRF valide) pour isoler les 401 de route du 403 middleware — 4 tests d'anonymat ajustés - suite **1026/1026** · `ruff check app tests` OK
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""Non-régression de l'audit sécurité 2026-09-30 — A11 (traversal) et A18 (XSS public)."""
|
||||
from conftest import anon
|
||||
from conftest import anon, anon_csrf
|
||||
|
||||
|
||||
def test_avatar_path_traversal_denied(client):
|
||||
@@ -60,6 +60,7 @@ def test_og_metadata_rejects_private_host(client):
|
||||
def test_automations_require_session(client):
|
||||
"""A13 : CRUD, run et press-button refusent un anonymous."""
|
||||
anon(client)
|
||||
anon_csrf(client)
|
||||
assert client.post("/workspace/automations", json={"name": "x"}).status_code == 401
|
||||
assert client.post("/workspace/automations/1/run", json={}).status_code == 401
|
||||
assert client.post("/api/automations/press-button", json={}).status_code == 401
|
||||
@@ -73,6 +74,7 @@ def test_outbound_webhook_requires_admin_and_public_url(client):
|
||||
assert r.status_code == 400
|
||||
|
||||
anon(client)
|
||||
anon_csrf(client)
|
||||
assert client.post("/workspace/webhooks", json={"url": "https://example.com/h"}).status_code == 401
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user