Skip to content

fix(observability): mask ?apikey= in the http.url span attribute - #1790

Open
rudycelekli wants to merge 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/tracing-span-url-apikey-20261025
Open

rudycelekli wants to merge 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/tracing-span-url-apikey-20261025

Conversation

@rudycelekli

Copy link
Copy Markdown
Contributor

Bug

When OTLP tracing is enabled (observability.tracing.enabled), TracingManager.HTTPMiddleware wraps the whole REST API router and records r.URL.String() as the http.url attribute of every span. That string includes the query.

?apikey= is an accepted credential (resolveAuth). The Web UI's SSE stream connects to /events?apikey=<admin key> (frontend/src/services/api.ts), and the tray sends the admin key the same way. So the admin API key lands in span attributes and is exported to the configured collector (Jaeger, Tempo, a shared OTel pipeline). Anyone who can read traces can then drive the REST API as admin.

httpLoggingMiddleware already masks the same query before it writes to http.log (SEC-01). The tracing middleware sees the same requests and was missed.

Trigger

Enable tracing, then open the Web UI. Every SSE (re)connect is a GET /events?apikey=… request, and each sampled one exports the key.

Fix

Build http.url from a copy of the request URL whose RawQuery has been passed through oauth.LogSafeQueryString, the same renderer http.log uses. The path and the non-secret parameters stay as they were. http.target and the span name already use only the path. internal/oauth does not import internal/observability, so the new import adds no cycle.

Test

TestHTTPMiddleware_MasksAPIKeyInSpanURL sends /events?apikey=<64-hex key>&limit=5 through the middleware with an in-memory span recorder. The recorded http.url must not contain the key, and must keep /events? and limit=5.

Commands run

  • CGO_ENABLED=0 go test -count=1 -run 'Test' ./internal/observability/: ok
  • On current main, and again with the fix reverted, the new test fails with http.url carries the API key: "/events?apikey=3f9a…b5c6&limit=5".
  • go vet ./internal/observability/: ok

The OTLP tracing middleware recorded r.URL.String() as http.url on every
REST API span. ?apikey= is an accepted credential, and the Web UI's SSE
stream (/events?apikey=...) and the tray send the admin key that way, so
with tracing enabled the admin key was exported to the collector.

Render the query through oauth.LogSafeQueryString, the renderer http.log
already uses for the same requests (SEC-01).
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

This branch has not been deployed

No deployments
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.

2 participants