Explorar el Código

Docs: mark R01-N19 fixed in f59f368

Sixteenth fix from doc/REVIEW_01.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa hace 2 días
padre
commit
99f985045d
Se han modificado 1 ficheros con 34 adiciones y 2 borrados
  1. 34 2
      doc/REVIEW_01.md

+ 34 - 2
doc/REVIEW_01.md

@@ -654,7 +654,37 @@ note. Do not delete entries — they're history.
 
 ### R01-N19 — Strict CSP has no `report-uri` / `report-to`
 - **Severity**: MEDIUM (operational visibility).
-- **Status**: open.
+- **Status**: fixed-in-`f59f368` — went with `report-uri` only (CSP
+  Level 1/2 directive, still honoured by every current browser; CSP3
+  `report-to` would have needed a `Reporting-Endpoints` response
+  header on every page and a second JSON parser for the
+  `application/reports+json` shape, neither cheap for the marginal
+  gain). `App\Http\FatalErrorHandler::CSP` gained
+  `report-uri /csp-report`. New public route `POST /csp-report`
+  routes to `App\Controllers\CspReportController::report`, which
+  body-caps at `MAX_BODY_BYTES = 16 * 1024` (real CSP reports are
+  well under 1 KiB; the cap is generous enough to never reject
+  legit reports, tight enough that a hostile client can't pump
+  megabytes of garbage into `audit_log`). The legacy
+  `{"csp-report": {...}}` envelope is unwrapped via the pure-static
+  `extractReport(string): ?array` helper; bare `{...}` shapes are
+  also accepted; top-level lists / scalars / non-JSON return null.
+  The endpoint is anonymous: no session, no CSRF — a browser fires
+  reports without session context most of the time, and a forged
+  report only costs one audit row (bounded by the cap). Always
+  responds 204 (no leaks about whether the report was accepted or
+  ignored). Audit row shape: `action=CSP_VIOLATION,
+  entity_type=csp_violation, entity_id=NULL,
+  before_json=NULL, after_json=<inner report>, user_id=NULL,
+  user_email=NULL, ip_address=<client>, user_agent=<browser>`.
+  `AuditRepository::distinctEntityTypes()` already powers the
+  `/audit` view's filter dropdown, so `csp_violation` shows up
+  there automatically. `FatalErrorHandlerTest` CSP-line assertion
+  grew a `report-uri` check (drift fence). New
+  `tests/Controllers/CspReportControllerTest.php` (10 cases) pins
+  the 204-always rule, the body cap, the JSON-object-only contract,
+  the envelope unwrap, and the audit-row shape end-to-end against
+  an in-memory DB. Tests: 266 / 721 (was 252 / 683).
 - **Where**: `public/index.php` lines 227-237.
 - **What**: CSP is strict but silent — operators won't notice if a future
   view inadvertently introduces an inline handler or new external host
@@ -935,7 +965,9 @@ A reasonable cadence (do not treat as binding):
 17. ~~**R01-N17** (concurrent-tab OIDC state)~~ — accepted-by-design;
     library uses fixed session keys, the realistic failure mode is a
     one-line UX nit, see Status block.
-18. The rest as time permits.
+18. ~~**R01-N19** (CSP `report-uri` + audit endpoint)~~ — fixed in
+    `f59f368`.
+19. The rest as time permits.
 
 Each fix should ship as its own commit per SPEC.md §14, with a follow-up
 SPEC update if behaviour or config surface changes.