From fd05563ec6dc305462133f4ec6094a95ccb881ac Mon Sep 17 00:00:00 2001 From: curo1305 Date: Sat, 6 Jun 2026 23:04:17 +0200 Subject: [PATCH] =?UTF-8?q?test(07.4):=20complete=20UAT=20=E2=80=94=204=20?= =?UTF-8?q?passed,=201=20fixed=20(fgp=20concatenation=20collision)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UAT found and resolved a concatenation collision in _compute_fgp (no separator between user_agent and accept_lang). Fix committed in c77b97b. All 5 FGP tests pass. Full suite: 401 passed, 6 skipped, 7 xfailed, 1 pre-existing failure (test_extract_docx — missing docx module, unrelated to this phase). Co-Authored-By: Claude Sonnet 4.6 --- .../07.4-UAT.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .planning/phases/07.4-security-token-fingerprinting-token-binding-inserted/07.4-UAT.md diff --git a/.planning/phases/07.4-security-token-fingerprinting-token-binding-inserted/07.4-UAT.md b/.planning/phases/07.4-security-token-fingerprinting-token-binding-inserted/07.4-UAT.md new file mode 100644 index 0000000..328dfda --- /dev/null +++ b/.planning/phases/07.4-security-token-fingerprinting-token-binding-inserted/07.4-UAT.md @@ -0,0 +1,66 @@ +--- +status: complete +phase: 07.4-security-token-fingerprinting-token-binding-inserted +source: [07.4-01-SUMMARY.md, 07.4-02-SUMMARY.md] +started: 2026-06-06T21:00:00Z +updated: 2026-06-06T21:10:00Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Cold Start Smoke Test +expected: Kill any running server/service. Start the application from scratch. Server boots without errors. Health check returns live response with all services healthy. +result: pass +notes: docker compose stop → rm -f → up -d; backend started clean, no errors in logs. GET /health returned {"status":"ok","checks":{"postgres":"ok","minio":"ok"}} + +### 2. Login and normal API access still work +expected: Log in with valid credentials. Access token returned with fgp claim embedded. Protected endpoint returns 200 — fgp embedding is transparent to the user. +result: pass +notes: Login returned ES256 JWT. Decoded payload confirmed fgp="9a27732e18cd110c" present. GET /api/documents with matching User-Agent returned HTTP 200. + +### 3. Fingerprint mismatch is rejected +expected: A token replayed from a different User-Agent should return HTTP 401 "Token fingerprint mismatch". +result: pass +notes: Token bound to Mozilla/5.0; replayed with "EvilBot/1.0 (stolen-token-replay)" and different Accept-Language. Response: {"detail":"Token fingerprint mismatch"} HTTP 401. Exact. + +### 4. Refresh flow preserved +expected: Refresh endpoint issues a new fgp-bound access token. New token works with same UA, fails with different UA. +result: pass +notes: Refresh returned new JWT with same fgp ("9a27732e18cd110c"). New token: 200 with matching UA, 401 with "AnotherBot/2.0". httpOnly refresh cookie correctly stored with #HttpOnly_ prefix in curl jar. + +### 5. FGP test suite passes (5/5) +expected: All FGP integration tests pass with no xfail stubs remaining. Full suite shows no new failures. +result: issue +reported: "4/4 tests passed initially. A concatenation collision vulnerability was found and fixed during UAT. A 5th regression test (FGP-05) was added. Full suite: 401 passed, 6 skipped, 7 xfailed, 1 failed (pre-existing docx ModuleNotFoundError). Final FGP suite: 5/5 passed." +severity: major +notes: Bug found and fixed in same session. See fix commit c77b97b. + +## Summary + +total: 5 +passed: 4 +issues: 1 +pending: 0 +skipped: 0 +blocked: 0 + +## Gaps + +- truth: "_compute_fgp must not accept different splits of the same concatenated string as equivalent fingerprints" + status: fixed + reason: "User reported: token bound to UA='foobar'+AL='' was accepted by UA='foo'+AL='bar' — same HMAC input without separator" + severity: major + test: 5 + root_cause: "Line 91 in backend/services/auth.py: `(user_agent + accept_lang).encode()` — no separator between the two fields allows concatenation collision" + artifacts: + - path: "backend/services/auth.py:91" + issue: "HMAC input lacks separator — user_agent + accept_lang ambiguous" + missing: + - "Null-byte separator between user_agent and accept_lang in HMAC input" + - "Regression test FGP-05 to prevent reintroduction" + fix_commit: "c77b97b" + fix_status: "resolved — separator added, regression test added, all 5 FGP tests pass"