Skip to content

fix: keep the route template, not the concrete path, on server spans - #17

Merged
vreshch merged 1 commit into
masterfrom
fix/redact-request-paths
Aug 9, 2026
Merged

fix: keep the route template, not the concrete path, on server spans#17
vreshch merged 1 commit into
masterfrom
fix/redact-request-paths

Conversation

@vreshch

@vreshch vreshch commented Aug 9, 2026

Copy link
Copy Markdown
Member

Companion to agentage/web#473, which stops mcp.tool.args carrying customer file paths. The REST surface leaks the same data through url.path, which is by definition the concrete request target:

url.path   /v1/memories/m/notes/00_INBOX/2026-08-04_bugs-y-decisiones.md
http.route /v1/^\/memories\/([^/]+)\/notes\/(.+)$/

The body is redacted upstream; the title telling you what the note is about was not.

The fix

When the instrumentation matched a route, keep the template on url.path instead of the concrete path. Same grouping value, no user data. url.full repeats the path, so it goes with it - the host stays in server.address.

Only when a route matched. An unmatched path (scanner probes, static assets - /files/index.php, /badge/agents-8%20+%20AGENTS.md) is not user content and stays verbatim; that is what makes a routing regression visible. Client spans are untouched.

Bonus: routes stop being unreadable

Express routes registered as a RegExp reach OTel as the regex source. readableRoute turns them back:

/v1/^\/memories\/([^/]+)\/notes\/(.+)$/   ->   /v1/memories/:param/notes/:path

Those were unusable as a facet in SigNoz and cryptic in a trace list, so this is worth having on its own.

Verified

  • npm run verify green, 51/51 across 9 files
  • New tests cover: template substitution, url.full removal, an assertion that no fragment of a title survives, unmatched paths left alone, client spans left alone, and both RegExp route shapes

Rollout

Kit change, so it reaches production only as services pick up the new version. Suggest releasing and bumping web (memory-mcp, backend, sync) first - that is where the content routes live; landing/catalog/dashboard/admin get the readable-route improvement whenever they next bump.

url.path is the concrete request target, so on a content route it carried the customer's own file path - the same data the memory-mcp body redaction already protects. When the instrumentation matched a route we now keep the template instead: same grouping value, no user data. url.full repeats the path, so it goes with it.

Only when a route matched. An unmatched path (scanner probes, static assets) is not user content and stays verbatim - that is what makes a routing regression visible.

Also un-mangles express RegExp routes, which reached OTel as the regex source: /v1/^\/memories\/([^/]+)\/notes\/(.+)$/ -> /v1/memories/:param/notes/:path. Those were unreadable in a trace list and useless as a facet.
@vreshch
vreshch force-pushed the fix/redact-request-paths branch from 25239a1 to 0dee820 Compare August 9, 2026 14:23
@vreshch
vreshch merged commit 7b7491c into master Aug 9, 2026
1 check passed
@vreshch
vreshch deleted the fix/redact-request-paths branch August 9, 2026 14:24
@vreshch vreshch mentioned this pull request Aug 9, 2026
vreshch added a commit that referenced this pull request Aug 9, 2026
Ships the request-path redaction from #17: on a matched route the span carries the route template, not the customer's concrete file path. README documents the behaviour under 'What gets traced'.

Also exports readableRoute, which un-mangles express RegExp routes from their regex source.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant