Skip to content

fix(router): stop logging secrets in ext_proc request logs#197

Open
Kyosuke Konishi (konippi) wants to merge 2 commits into
agent-substrate:mainfrom
konippi:fix/stop-logging-secrets
Open

fix(router): stop logging secrets in ext_proc request logs#197
Kyosuke Konishi (konippi) wants to merge 2 commits into
agent-substrate:mainfrom
konippi:fix/stop-logging-secrets

Conversation

@konippi

@konippi Kyosuke Konishi (konippi) commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Part of #103.

Stops the router (ext_proc) request path from writing secrets to logs.

This PR was prepared in part with the assistance of generative AI.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

@bowei

Copy link
Copy Markdown
Collaborator

The ext_proc changes look ok. If you split that into its own PR, I can review and merge that.

@konippi Kyosuke Konishi (konippi) changed the title fix: stop logging secrets in request and RPC logs fix(router): stop logging secrets in ext_proc request logs Jun 11, 2026
@konippi

Copy link
Copy Markdown
Contributor Author

Bowei Du (@bowei)
Thanks! Scoped this down to just the ext_proc changes.

The other two pieces are split out:

headersMap[k] = val
if k == ":path" {
path = val
path, _, _ = strings.Cut(val, "?")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to use url.Parse to avoid potential edge cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried both. For :path, cutting at the first ? removes exactly the query, which is the secret vector here.

url.Parse doesn't improve that for this use and adds downsides:

  • It errors on e.g. control chars, so it needs a fallback — and a fallback that logs the raw value would leak the query. strings.Cut is total, so there's no error path that can fall through to logging the secret.
  • It reinterprets //host/path as authority and silently drops it.

Given that, my inclination would be to keep strings.Cut — but I'm very open to using url.Parse if you'd prefer. Let me know what you think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, do we need this change?

I think interpreting the path: coming from Envoy would add some additional non-obvious semantics to this code. If we maintain that we pass the Envoy argument through unchanged, this will be much simpler to explain how this works.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a security issue that you are trying to fix?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — the :path query string can carry secrets (tokens, OAuth codes, etc.; CWE-598), and m.path gets persisted into the statusz QueryRecorder, which is served unauthenticated. That's the leak I'm closing.

You're right that the parser shouldn't reinterpret :path. I've reverted newRequestMetadata to pass Envoy's :path through verbatim and moved the query-stripping to the sink (redactPath in AddRouterRequest) — same "redact at the sink" approach as sanitizeForLog.

@bowei Bowei Du (bowei) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment on the path change. Otherwise looks ok

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