fix(api): authenticate reflector endpoints + pin govulncheck (security P0) - #398
Merged
Conversation
POST/GET /api/v1/reflector/{config,stats} were registered with only a rate
limiter (no auth) — any client on the network could reconfigure or inspect the
dataplane. Route them through handleAuthRateLimited so a valid token is
required; update the reflector tests to the authenticated behavior (and invert
the old 'endpoints don't require auth' test).
Also pin govulncheck @latest -> @v1.3.0 per CLAUDE.md (never @latest).
Phase 0 of the stem security hardening. CSRF rekey + CORS allowlist follow.
Contributor
License Compliance ReportAll dependencies pass license compliance checksGo Dependencies
npm DependenciesSee full report in workflow artifacts Allowed Licenses: MIT, Apache-2.0, BSD-*, ISC, CC0-1.0, MPL-2.0 |
krisarmstrong
enabled auto-merge (squash)
June 7, 2026 04:47
krisarmstrong
added a commit
that referenced
this pull request
Jun 8, 2026
#401) Routes are now declared as data and a single register()/registerAll() composes their per-route policy — rate limit, authentication — in one canonical order, so a route cannot ship without its policy. This replaces the scattered imperative handleAuthRateLimited/handleRateLimited/mux.Handle calls where the wrapper nesting could be forgotten — the regression class that left POST /api/v1/reflector/config unauthenticated (#398). - internal/api/route.go: route{} + register()/registerAll() + methodGate, a routeManifest, and the /__capabilities introspection endpoint. - setupRoutes: all ~40 API routes converted to declarative route{} entries, preserving each route's exact auth flag + rate limiter. Removed the now-unused handleAuthRateLimited/handleRateLimited helpers. - scripts/check-route-policy.sh: CI gate failing if any /api route is registered directly instead of via register(). Wired into ci.yml. - route_test.go: asserts /__capabilities records policy (reflector=auth, login=no-auth). Enforcement by construction (Phase 3). Full internal/api suite green; golangci golden config 0 issues. niac registry follows. Co-authored-by: Kris Armstrong <kris.armstrong@icloud.com>
This was referenced Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 0 — stem security P0 (per the stem/niac remediation plan).
What
POST/GET /api/v1/reflector/{config,stats}were registered with rawmux.Handle+ only a rate limiter — no authentication. Any network client could reconfigure or inspect the dataplane. Now routed throughhandleAuthRateLimited(auth + rate limit), matching every other mutating route.@latest->@v1.3.0(CLAUDE.md: never@latest).Tests
Updated the reflector tests to authenticate (the suite previously encoded the insecure assumption that these endpoints were open). Added/inverted
TestReflectorEndpointsRequireAuthto assert unauthenticated access now returns 401. Fullinternal/apipackage passes.Scope note
This is the bounded, high-impact slice. CSRF rekey to
sha256(session)+ fail-closed, and the CORS operator-allowlist (Config.Validate()), follow as separate Phase-0 changes (they need care not to break the setup/recovery flow and LAN-appliance access).