Redact credential-bearing base-url path segments before they reach logs or error strings #93
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#93
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Handed over from
coilyco-flight-deck/infrastructure#708, where a Telegram bot credential was exposed for 22 days in notification-failure log output and had to be rotated.What happened
The
signoz-telegrammapper is configured with abase-urlthat is the credential:Telegram carries its bot token in the URL path rather than a header or a query parameter, and
base-urltakes a single env value, so the deploy side has no way to supply the token separately. From the manifest's own comment incoilyco-bridge/deploy:That is a reasonable workaround given what beaver offers today. The consequence is that any code path reporting a failing request by echoing its URL emits the credential verbatim, which is exactly what happened.
Why rotation did not fix it
Rotation replaces the burned value. It does nothing about the mechanism, so the next notification failure burns the new credential the same way.
infrastructure#708should not close until this lands.Worth noting for whoever picks this up: the failure path is the leak, so it cannot be safely exercised against a live credential. Reproduce against a throwaway token.
Two candidate fixes
auth query-paramalready exists for the query case, so this is the path-shaped sibling of a pattern beaver has./bot<id>:<secret>style segment in any URL before it reaches a log line, error string, or trace attribute.Recommend doing 2 regardless, and 1 as well if it is cheap. Redaction is the stronger guarantee because it holds even when a future caller reintroduces a credential-bearing base URL by configuration, which is precisely how this arose. Composition alone leaves the same trap open for the next integration whose API puts a secret in the path.
A general form is probably better than a Telegram-specific pattern: treat any base-url-derived path segment as sensitive by default, since an operator only puts a secret in a base URL when the upstream API forces it.
Acceptance
A deliberately failed upstream call produces a log line, error string, and trace attribute containing a redacted path segment and no token material. Cover the success path too, so a future change that starts logging request URLs on success does not reopen this.
Context
coilyco-flight-deck/infrastructure#708services/signoz-telegram/incoilyco-bridge/deploy,kai-server-externalsecret.ymlandsignoz-telegram.mcp.kdl/api/create_alertCorrecting the framing I filed this under. This is hardening, not the cause.
I filed this believing beaver's URL-as-credential shape produced the
infrastructure#708exposure. Checking SigNoz retention afterwards showed otherwise. All 36 retained token-bearing log records over 30 days come from one container:Zero from
signoz-telegram. Gatus keeps its own direct Telegram path, independent of this mapper by design, and it is the unit that logged the credential. Beaver has not been observed leaking anything.What stands unchanged is the shape: this mapper is configured with a
base-urlthat is itself a credential, because Telegram puts its token in the path andbase-urltakes one env value. That is a live trap even though it has not sprung. A caller who adds request-URL logging on an error path turns it into the same incident.So this stays open and the acceptance criteria are unchanged, but the priority is defence in depth rather than incident remediation. The actual
infrastructure#708fix is a SigNoz ingest-side redaction pipeline, which covers Gatus and any future unit that logs a credential-bearing URL, including this one if it ever starts.