Repository navigation
Neutral per-site intake paths (/e/{site}) - #146
Conversation
Per-site scripts loaded straight from SUPERMETRY_BASE_URL post events to /e/<site>, and the replay loader and recorder use /e/<site>/r.js, /s, /c and /k/<hash>. Scripts served through a first-party proxy keep the classic paths. Lazy modules are requested by short code (?m=v,h,r); ?module= still works. SUPERMETRY_NEUTRAL_PATHS=false turns it off.
/e/{site}, /e/{site}/s, /c, /k/{hash} and /e/{site}/r.js are aliases of the
event, replay and recorder routes. Ingest and replay reject a body or ?s=
naming another site, and the routes get the cross-origin intake headers.
Findings
|
| Layer / File(s) | Summary |
|---|---|
Configure paths and generate tracker URLs .env.example, internal/config/config.go, internal/config/config_test.go, internal/tracker/script.go, internal/tracker/script_test.go, docs/guide/configuration.md, CHANGELOG.md |
Neutral paths default to enabled and can be disabled with SUPERMETRY_NEUTRAL_PATHS. The tracker selects a per-site event path for matching base URLs. Lazy-module requests use short codes while accepting the long-form parameter. |
Route neutral requests internal/api/neutral.go, internal/api/neutral_test.go, internal/api/router.go, cmd/supermetry/serve.go, cmd/supermetry/serve_http_test.go, docs/guide/configuration.md, CHANGELOG.md |
The router registers neutral site routes. The neutral handler validates paths, forwards supported requests to legacy handlers, and serves the recorder script. Route classification applies intake or tracker security policy. |
Check path and request site IDs internal/ingest/pathsite.go, internal/ingest/handler.go, internal/ingest/handler_test.go, internal/replay/handler.go, internal/replay/handler_test.go |
Requests forwarded from neutral paths carry the path site ID in their context. Event ingestion and replay start return a bad request response when the request site does not match it. |
Select replay endpoints internal/tracker/tracker.replay.js, internal/tracker/tracker_replay_runtime_test.js, internal/replay/static/src/replay.ts |
The tracker loads the recorder from the neutral path when available and passes that path to the replay client. The replay client selects neutral endpoints for starts, chunks and CSS uploads, with classic endpoints as fallback. |
Possibly related PRs
- velixio/supermetry#116: Changes tracker endpoint derivation and preserves first-party proxy prefixes, which this PR extends with neutral-path selection.
- velixio/supermetry#113: Changes replay asset and upload URLs to preserve first-party proxy prefixes, which this PR extends with neutral replay paths.
Merge Risk: 
Low · up to 73249
-
Replay recording can fail for a proxied site whose custom event path ends in its site ID. Fix the replay path selection before merging if that configuration is in use.
Security architecture risk: 
Moderate · up to 73249
-
Site identity checks are preserved, but deployment safety depends on updating the gateway first. The off switch changes generated client URLs, not endpoint availability, so it cannot by itself restore gateway controls during an incompatible rollout or rollback.
Retained concerns
- High · security · inferred: The new aliases are served even when SUPERMETRY_NEUTRAL_PATHS=false. If the gateway companion change is absent or rolled back while these aliases remain reachable, callers can select /e/ paths to avoid the suspension, replay-allowance and proxy-key checks identified in the PR's deployment prerequisite. Disabling client URL generation alone does not close this conditional exposure; actual gateway enforcement remains unverified.
Security review details
-
Security Blast Radius
- inferred — The conditional gateway exposure is not limited to one site: the aliases accept caller-selected public site IDs across sites served by an affected gateway. Effective writes still require application-level site, origin, policy and session admission. The traced outcomes are event collection and replay/CSS storage, not administrative access or cross-site reads.
Security Findings and Attack Paths
- inferred — The unresolved attack path is a caller choosing a neutral URL that an older gateway forwards without its classic-path controls. Path/body equality does not replace those controls. The prerequisite is explicit in the PR, but gateway forwarding behavior and deployment order were not independently established, so this remains a conditional architecture concern rather than a verified deployed vulnerability.
Trust Boundaries and Controls
- observed — The path site is a consistency constraint, not an authenticated credential. Existing registry lookup and collection controls remain authoritative. Replay's returned version is a public policy fingerprint, not a token granting ownership or proving consent; production CSS uploads retain the collection guard. These controls predate the aliases and provide counterevidence against a new application-level identity bypass.
Hardening Proposals
- proposed — Make gateway enforcement parity a release and rollback prerequisite for every neutral intake form. A separate server-side alias gate, or an edge deny rule until parity is confirmed, would provide containment that the client-routing switch does not provide.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 31.03% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 29 functions across 17 files. (3 skipped: 3 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Ad blockers block well-known analytics URLs such as
/api/public/v1/events,/replay.jsand/api/replay/*. This PR gives every site its own intake paths under/e/<site public ID>.Server
POST /e/{site}(events),GET /e/{site}/r.js(recorder),POST /e/{site}/s(replay start),POST /e/{site}/c(chunk) andPUT /e/{site}/k/{hash}(stylesheet) are aliases. Each one rewrites the request to the classic path and calls the existing handler.?s=that names a different site from the path.r.jsloads on customer sites.Tracker
SUPERMETRY_BASE_URLsends to/e/<site>. Loaded from any other origin, such as a first-party proxy that forwards only the classic paths, it keeps the classic paths, so existing proxies and SDK proxy helpers keep working./e/<site>.?m=v,h,rinstead of?module=vitals,heatmap,replay. The long form is still accepted.SUPERMETRY_NEUTRAL_PATHS=falseturns the tracker change off.Deploy order
The Cloud gateway must recognise
/e/paths before this ships, or neutral traffic skips the suspension, replay-allowance and proxy-key checks: velixio/supermetry-cloud#59.Verification
go vet ./..., plusgo test ./...against the test database: all pass.POST /e/<id>returned 202 and the event was stored. A wrong site returned 400. The preflight returned 204 withACAO *and cross-origin CORP.r.jsis identical to/replay.js. Replay start returned 200.