소스 검색

docs: mark SEC_REVIEW F39 as fixed in 0c79c1b

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa 4 일 전
부모
커밋
35645140e0
1개의 변경된 파일20개의 추가작업 그리고 1개의 파일을 삭제
  1. 20 1
      doc/SEC_REVIEW.md

+ 20 - 1
doc/SEC_REVIEW.md

@@ -11,7 +11,7 @@
 >
 > Each finding is referenced as **F<N>** for later citation.
 >
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (6 fixed, 36 open).
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (7 fixed, 35 open).
 
 ---
 
@@ -1340,6 +1340,25 @@
   parser should refuse base32 strings whose final character has the
   unused bit set.
 - **Severity: 1**
+- **Status:** Fixed. The original review concern was based on the
+  visible `if (strlen($chunk) < 5) { $chunk = str_pad($chunk, 5, '0'); }`
+  branch in `TokenIssuer::base32Encode`. For the actual input —
+  `random_bytes(20)` = 160 bits — that branch was unreachable: 160 ÷ 5
+  = 32 with zero remainder, every base32 char in the 32-char output
+  carries a full 5 useful bits, and there is exactly one canonical
+  encoding per input. So there are no unused trailing bits and no
+  ambiguity in the existing scheme. The dead `str_pad` branch (the
+  source of the false-positive impression) is removed; the encoder
+  now hard-asserts `strlen($bytes) === 20` and throws
+  `InvalidArgumentException` otherwise, so any future caller that
+  passes a different length crashes loudly rather than silently
+  emitting a non-canonical / shorter token. The 20-byte length is
+  pinned via a new `TokenIssuer::ENTROPY_BYTES = 20` constant. The
+  parser (`Token::parse`) keeps its `^[A-Z2-7]{32}$` body pattern;
+  every 32-char base32 string is canonical for this scheme so no
+  additional canonicality gate is needed. Regression test
+  `TokenIssuerTest::testIssuedBodyAlwaysExactlyThirtyTwoBase32Chars`
+  asserts the invariant across 100 fresh issuances.
 
 ### F40 — CSRF token never rotated on session-id regeneration
 - **Files:** `ui/src/Http/CsrfMiddleware.php:53-60`,