Bläddra i källkod

Docs: mark R01-N02 / R01-N31 fixed, refresh SPEC §9 / §11 / §13

- doc/REVIEW_01.md: flip R01-N02 (HIGH, anonymous homepage info disclosure)
  and R01-N31 (LOW, /healthz hint) to fixed-in-7fd849b. Same fix closes
  both because the /healthz link lived inside the same Runtime <details>.
  Strike out R01-N02 in the suggested ordering; next open finding in the
  cadence is R01-N04 (SESSION_SECRET doc cleanup).
- SPEC §9: insert a new shipped entry for the fix above the "New sprint
  form" entry, with rationale and the new test count.
- SPEC §11: 149 / 424 → 150 / 430.
- SPEC §13: append 7fd849b plus the two missing prior SHAs (912ef9b,
  756650a) so the history block stays current.

Per the §14 maintenance contract: code committed first (7fd849b), docs
ship as their own commit so a future revert can roll either side back
without dragging the other.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa 2 dagar sedan
förälder
incheckning
18389bb4b3
2 ändrade filer med 30 tillägg och 5 borttagningar
  1. 18 1
      SPEC.md
  2. 12 4
      doc/REVIEW_01.md

+ 18 - 1
SPEC.md

@@ -1046,6 +1046,20 @@ with a `BOOTSTRAP_ADMIN` audit row.
       unchanged. *New sprint* stays in the header as the one
       quick-action admins reach for from any page.
 
+- [x] **R01-N02 / R01-N31 — Runtime panel on `/` is now admin-only**
+      (`7fd849b`). `views/home.twig`'s "Runtime" `<details>` block was
+      previously rendered for anonymous visitors as well as admins,
+      leaking `PHP_VERSION`, `APP_ENV`, the SQLite file path, the schema
+      version, and the OIDC / local-admin enablement flags — useful
+      reconnaissance for anyone scanning the public homepage. The twig
+      guard tightened from `currentUser is null or currentUser.isAdmin`
+      to `currentUser is not null and currentUser.isAdmin`. Same edit
+      removes the in-page `/healthz` hint (R01-N31); the route itself
+      stays public for liveness probes. New
+      `TwigViewTest::testHomeForAnonymousUserHidesRuntimePanel` locks
+      the behaviour in. Tests: 150 / 430 (was 149 / 424). First fix
+      from `doc/REVIEW_01.md`.
+
 - [x] **New sprint form: drop weeks input + task list row hover**
       (`3728106`). The `/sprints/new` form no longer collects an
       `n_weeks` value — the week count is derived from `start_date` /
@@ -1114,7 +1128,7 @@ for f in $(git ls-files '*.php'); do php -l "$f" | tail -1 | sed "s|^|$f: |"; do
 Run the test suite:
 ```bash
 vendor/bin/phpunit
-# → OK (149 tests, 424 assertions)
+# → OK (150 tests, 430 assertions)
 ```
 
 The Phase 20 parser tests need `ext-dom`, `ext-zip`, `ext-xmlreader`,
@@ -1161,6 +1175,9 @@ before acting — nothing here is load-bearing once it grows stale.
 ## 13. Git history (as of this writing)
 
 ```
+7fd849b Fix R01-N02 / R01-N31: gate runtime panel on home page to admins
+912ef9b doc/REVIEW_01.md: initial security + fishy-pattern audit
+756650a SPEC.md: note new-sprint form weeks-drop + task list row hover
 3728106 New sprint form: drop weeks input + task list row hover
 fe78f45 Header: move Import link into the admin dropdown menu
 8e8b8fd Sprint settings: secured Delete sprint action

+ 12 - 4
doc/REVIEW_01.md

@@ -65,7 +65,13 @@ note. Do not delete entries — they're history.
 
 ### R01-N02 — Information disclosure to anonymous users on `/`
 - **Severity**: HIGH (signal to anyone scanning the public homepage).
-- **Status**: open.
+- **Status**: fixed-in-`7fd849b` — twig guard tightened from
+  `currentUser is null or currentUser.isAdmin` to
+  `currentUser is not null and currentUser.isAdmin`; new
+  `TwigViewTest::testHomeForAnonymousUserHidesRuntimePanel` asserts the
+  panel and its leaked strings are absent for `currentUser=null`. Closes
+  R01-N31 as a side effect (the in-page `/healthz` hint lived inside the
+  same `<details>`).
 - **Where**: `views/home.twig` lines 112-138 — the "Runtime" `<details>`
   panel.
 - **What**: When `currentUser is null`, the panel still renders. It exposes:
@@ -528,7 +534,9 @@ note. Do not delete entries — they're history.
 
 ### R01-N31 — `home.twig` link to `/healthz` is a tiny info-disclosure
 - **Severity**: LOW.
-- **Status**: open.
+- **Status**: fixed-in-`7fd849b` — folded into the R01-N02 fix; the
+  `<a href="/healthz">` line lives inside the now admin-only Runtime
+  panel, so anonymous users no longer see it.
 - **Where**: `views/home.twig` line 135.
 - **What**: A textual hint to the existence of `/healthz`. Liveness probes
   are normally undocumented to discourage scanning; the route returns
@@ -621,8 +629,8 @@ These are not findings; recorded so we don't re-investigate later:
 
 A reasonable cadence (do not treat as binding):
 
-1. **R01-N02** (homepage info disclosure) — 10-line edit, big perception
-   win.
+1. ~~**R01-N02** (homepage info disclosure)~~ — fixed in `7fd849b`. Also
+   closes R01-N31.
 2. **R01-N04** (`SESSION_SECRET` doc cleanup) — pure docs.
 3. **R01-N15** (`rel="noopener noreferrer"`) — one-character fix.
 4. **R01-N11** (audit column whitelist) — defensive, trivial.