Files
summercms/.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-11-PLAN.md
2026-09-20 16:14:21 +02:00

18 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, gap_closure, requirements, must_haves
phase plan type wave depends_on files_modified autonomous gap_closure requirements must_haves
06-http-routing-auth-groups-and-rate-limiting 11 execute 7
06-07
06-08
06-09
06-10
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md
true true
HTTP-03
HTTP-04
HTTP-05
HTTP-06
HTTP-07
HTTP-08
HTTP-09
truths artifacts key_links
The security review no longer claims zero open threats until all four corrective plans and both repositories' complete `go test ./... -count=1 -race -short` gates pass
T-06-24 records the anonymous key as exactly `inline:domainless|<ClientIP>` and explicitly excludes the throttle parameter, `r.Host`, `Forwarded` host, and `X-Forwarded-Host` from bucket selection
T-06-23 through T-06-27 map atomic admission, domainless inline keys, transition-address SSRF rejection, clean partial-write panic recovery, and exact InvScope bytes to named passing tests
T-06-24 cites the named Plan 06-07 Host-rotation, cross-inline-parameter shared-budget, and authenticated `u:<id>` isolation regressions
The review's verdict, scope, totals, accepted-risk count, and audit trail agree with the post-fix code and evidence
Any failed corrective test leaves the review open/blocked rather than documenting a false verified state
path provides
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md Post-gap Phase 6 ASVS L1 threat map and evidence-backed verdict
from to via pattern
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md summercms.go/surf/limiter_test.go T-06-23/T-06-24 cite the coordinated concurrency plus the named `TestFixedWindowLimiterInlineThrottleKeys` Host-rotation, cross-inline-parameter shared-budget, and authenticated-principal isolation cases TestFixedWindowLimiterInlineThrottleKeys
from to via pattern
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md summercms.go/fetchguard/ip_test.go T-06-25 cites NAT64/6to4 embedded-private and public-control cases T-06-25
from to via pattern
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md summercms.go/surf/router_test.go T-06-26 cites raw and house partial-write panic regressions T-06-26
from to via pattern
.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md fonoteka.go/plugins/golem15/fonoteka/middleware/token_scope_test.go T-06-27 cites exact no-newline 401/403 byte assertions T-06-27
Refresh the Phase 6 ASVS L1 security review only after all corrective code and tests are green, replacing the stale zero-open conclusion with a complete post-gap threat map and auditable evidence.

Purpose: the review is itself a required phase artifact. Its verdict must describe the current code, not the pre-review snapshot that missed four security/contract failures. Output: an updated 06-SECURITY-REVIEW.md covering Plans 06-01 through 06-10 plus the Plan 06-11 review refresh, with all five new threats accurately closed or the phase explicitly blocked.

<execution_context> @/home/jin/.codex/get-shit-done/workflows/execute-plan.md @/home/jin/.codex/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/REQUIREMENTS.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-CONTEXT.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-VERIFICATION.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-REVIEW.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-07-SUMMARY.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-08-SUMMARY.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-09-SUMMARY.md @.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-10-SUMMARY.md Task 1: Re-run Phase 6 security gates and publish the post-gap threat verdict .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md (current stale header, threat register, findings, accepts, and audit trail; preserve all still-valid evidence) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-VERIFICATION.md (authoritative four code gaps plus stale-review gap) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-REVIEW.md (CR-01 through CR-04 and WR-11 source evidence) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-07-PLAN.md and 06-07-SUMMARY.md (T-06-23/T-06-24 and actual test names/results) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-08-PLAN.md and 06-08-SUMMARY.md (T-06-25 and actual transition tests/results) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-09-PLAN.md and 06-09-SUMMARY.md (T-06-26 and actual recovery tests/results) .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-10-PLAN.md and 06-10-SUMMARY.md (T-06-27 and actual byte-contract tests/results) surf/limiter.go, surf/limiter_store.go, surf/limiter_test.go (executed atomic admission and stable-key code/evidence) fetchguard/ip.go, fetchguard/ip_test.go, fetchguard/fetch_test.go (executed transition classifier and dial-time evidence) surf/router.go, surf/router_test.go (executed buffer/discard recovery and partial-write evidence) ../fonoteka.go/plugins/golem15/fonoteka/middleware/token_scope.go and token_scope_test.go (executed no-newline writer and exact-byte evidence) Before editing the review, run the repository-level verification commands below. The authoritative suite gates are exactly `go test ./... -count=1 -race -short` from summercms.go and the same command from sibling fonoteka.go; package-targeted race runs or full suites without `-race` are not substitutes. If any command fails, do not set `status: verified`, do not set `threats_open: 0`, and do not add a zero-open audit row; stop and report the failing threat/test as blocking. High-severity T-06-23 through T-06-26 may not be accepted or deferred.
After all gates pass, update `06-SECURITY-REVIEW.md` frontmatter date/status/threat count and scope so it explicitly covers Plans 06-01 through 06-10 and the Plan 06-11 review refresh. Preserve every existing T-06-01..18, T-06-21, T-06-22, and T-06-SC row and its disposition unless the new code invalidates the old evidence; do not erase accepted-risk rationales or prior audit-trail rows.

Add five mitigate rows and matching detailed `Findings by Threat` sections using the actual executed test names from the four summaries: T-06-23 for atomic threshold check+increment and coordinated Max=1 evidence; T-06-24 for the server-controlled `inline:domainless|<ClientIP>` key; T-06-25 for RFC 6052 well-known/local-use NAT64 plus 6to4 embedded loopback/RFC1918/metadata rejection, public controls, and dialControl proof; T-06-26 for buffer/discard recovery with both raw and house partial-write-then-panic exact response assertions; T-06-27 for `wire.WriteJSON` and raw-byte 401/403 assertions with no trimming. For T-06-24, state explicitly that the anonymous key excludes the throttle `param`, `r.Host`, the `Forwarded` host parameter, and `X-Forwarded-Host`. Cite the exact executed names recorded by Plan 06-07's summary/source for all three inline-key regressions under `TestFixedWindowLimiterInlineThrottleKeys`: the Host-rotation subtest, the same-IP shared-budget subtest spanning different inline throttle parameters, and the authenticated-principal subtest proving independent `u:<id>` buckets. Copy the complete slash-qualified names from the executed test source/summary rather than describing unnamed cases. Do not reduce this to a Host-rotation citation or claim that a throttle parameter selects any portion of the anonymous key. Cite concrete source identifiers and named tests, not only plan numbers.

Update the trust-boundary table for concurrent limiter admission, IPv6 transition decoding, buffered response commit, and token-scope serialization. Update summary prose, accepted-risk count, closed/open totals, and Security Audit Trail consistently. With the existing 21 reviewed IDs plus five new mitigations, the successful review total is 26 threats, 26 closed, zero open; T-06-SC remains one of the 26 and no new accepted risk is introduced. Do not change `06-VERIFICATION.md`; re-verification remains the verifier's next step.
cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && go test ./... -count=1 -race -short && go vet ./... && cd ../fonoteka.go && go test ./... -count=1 -race -short && go vet ./... && cd ../summercms.go && test "$(awk -F'|' '/^\| T-06-(23|24|25|26|27) / {c++} END {print c+0}' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md)" -eq 5 && rg -n '26 \| 26 \| 0|threats_open: 0|Plans 06-01 through 06-10' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && rg -n 'inline:domainless\|<ClientIP>' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && rg -n 'TestFixedWindowLimiterInlineThrottleKeys/.+(Host|host)' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && rg -n 'TestFixedWindowLimiterInlineThrottleKeys/.+(param|policy)' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && rg -n 'TestFixedWindowLimiterInlineThrottleKeys/.+(principal|authenticated|user)' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && rg -n 'u:<id>' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md && ! rg -n 'inline:<param>\|<ClientIP>|param\+ClientIP|anonymous (bucket|key).*(uses|includes|contains|combines).*(throttle )?param' .planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-SECURITY-REVIEW.md - The review update occurs after all four plan summaries exist and `go test ./... -count=1 -race -short` plus `go vet ./...` exit 0 in both summercms.go and fonoteka.go. - The Threat Register contains exactly one row each for T-06-23, T-06-24, T-06-25, T-06-26, and T-06-27, all disposition `mitigate`, each naming executed source/test evidence. - Findings by Threat contains substantive sections for all five new IDs: coordinated concurrency; exact `inline:domainless|` construction; named Host-rotation, cross-inline-parameter shared-budget, and authenticated `u:` isolation regressions; all three transition prefixes; both partial-write route kinds; and raw exact 401/403 bytes. - T-06-24 says the anonymous signature excludes throttle `param`, `r.Host`, `Forwarded` host, and `X-Forwarded-Host`; the source/verification grep rejects stale `inline:|`, `param+ClientIP`, or equivalent parameter-selected anonymous-key claims. - Frontmatter, summary, accepted-risk log, threat totals, and the newest audit-trail row agree on 26 total, 26 closed, zero open only when every gate passed. - Every earlier threat row and audit-trail history remains present; no high-severity gap is silently accepted, deferred, or omitted. - `06-VERIFICATION.md` is not edited by this plan. The Phase 6 security review truthfully reflects the corrected code and supplies auditable, named test evidence for every previously unresolved security/contract gap.

<threat_model>

Trust Boundaries

Boundary Description
implementation evidence -> security verdict A stale or optimistic review can falsely release security-load-bearing primitives to dependent phases
test gates -> documentation state Zero-open status is allowed only when the exact adversarial tests and both repository suites pass

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-06-23 Denial of Service concurrent limiter admission mitigate Require atomic Attempt implementation and coordinated Max=1 passing evidence before review closure
T-06-24 Denial of Service anonymous inline key selection mitigate Require exact `inline:domainless
T-06-25 Elevation of Privilege / Information Disclosure transition-address SSRF classification mitigate Require NAT64 /96, local-use NAT64 /48, and 6to4 embedded-private plus dialControl tests
T-06-26 Information Disclosure raw/house panic recovery mitigate Require partial-write status/header/body discard tests for both route kinds
T-06-27 Tampering personal-token denial serialization mitigate Require wire.WriteJSON and exact untrimmed 401/403 byte comparisons
T-06-SC Tampering package supply chain accept Gap plans add no dependencies; retain the existing Phase 6 package-legitimacy disposition
</threat_model>

<source_coverage_audit>

Source ID Feature / Requirement Plan Status Notes
GOAL Phase 6 Secure shared auth groups, 1:1 rate limiting, raw OAuth boundary, and SSRF guard 06-07..06-11 COVERED Four defects fixed in parallel; review refresh follows all code/test plans
REQ HTTP-03 Mutually exclusive groups share handlers 06-11 COVERED (existing + regression gate) Implemented by 06-01/06-05; full suite confirms no regression
REQ HTTP-04 Named/inline rate limits and stacking 06-07, 06-11 COVERED Atomic admission and exact `inline:domainless
REQ HTTP-05 Unified guard registry/current-user accessor 06-10, 06-11 COVERED Existing registry retained; exact personal-token denial contract is verified
REQ HTTP-06 Response conventions and raw exemption 06-09, 06-10, 06-11 COVERED Clean partial-write recovery and no-newline TokenScope bytes
REQ HTTP-07 Guarded outbound fetch 06-08, 06-11 COVERED Transition addresses receive embedded IPv4 classification at dial time
REQ HTTP-08 OpenAPI/type generation 06-11 COVERED (existing + regression gate) Implemented by 06-03; no authoritative current gap requests replanning
REQ HTTP-09 CORS/body limits 06-11 COVERED (existing + regression gate) Implemented by 06-03; no authoritative current gap requests replanning
RESEARCH Fixed-window semantics First-hit fixed window and PHP headers/body 06-07 COVERED Atomic API preserves the established sequential contract
RESEARCH SSRF dial-time guard Actual connected address is classified 06-08 COVERED Transition extraction feeds the existing dial-time classifier
CONTEXT D-01..D-05 Five buckets, fixed-window parity, stdlib store, trusted ClientIP, parameterized names 06-07 COVERED No bucket limit/key ownership or middleware syntax is reduced
CONTEXT D-06..D-10 Guard registry, real token guard, exact InvScope bodies, no OAuth stub, unchanged JWT 06-10 COVERED D-08 exact bytes repaired; remaining decisions preserved
CONTEXT D-11..D-14 AllowHosts/PublicOnly, dial-time rejection, typed failures, caps/timeouts 06-08 COVERED Transition forms added without changing caller scope or limits
CONTEXT D-15..D-18 Group subsets, raw bare recovery, response conventions/OpenAPI, CORS/body limits 06-09, 06-11 COVERED D-16 is upheld after partial writes; unrelated existing outputs regression-tested
CONTEXT Deferred Ideas Later route handlers/call sites — EXCLUDED Explicitly out of Phase 6 and absent from authoritative gaps:
REVIEW Warnings outside verifier gaps WR-01..WR-10 except promoted WR-11 — EXCLUDED Gap-closure mode plans only authoritative 06-VERIFICATION.md gaps; these remain review backlog, not silently claimed fixed
</source_coverage_audit>
Run `go test ./... -count=1 -race -short` and `go vet ./...` in both repositories before documentation can claim verified/zero-open. Validate five new unique threat rows, matching detailed findings, consistent 26/26/0 totals, preserved prior evidence, and a scope statement covering the corrective plans. Assert positively that T-06-24 names `inline:domainless|` and the three Plan 06-07 inline-key regressions, and fail if the review contains `inline:|`, `param+ClientIP`, or an equivalent parameter-selected anonymous-key claim. If any command or assertion fails, leave the verdict open and stop.

<success_criteria>

  • The stale Phase 6 security verdict is replaced by evidence matching the post-gap code.
  • T-06-23 through T-06-27 are each closed by concrete named tests, never by assertion alone.
  • T-06-24 documents only inline:domainless|<ClientIP>, explicitly excludes throttle param and all request/forwarded Host input, and cites the named Host-rotation, cross-inline-parameter shared-budget, and authenticated u:<id> isolation tests.
  • The successful audit is internally consistent at 26 total / 26 closed / 0 open with no new accepted risk.
  • A failed full-repository -race suite, vet gate, or anonymous-key source assertion in either repository cannot produce a verified/zero-open document.
  • All four source categories are fully covered without planning deferred items or non-authoritative warnings. </success_criteria>
Create `.planning/phases/06-http-routing-auth-groups-and-rate-limiting/06-11-SUMMARY.md` when done.