fix: Redact all credential-bearing URL components in the status dbServer field - #879
Merged
Merged
Conversation
keelerm84
force-pushed
the
mk/SDK-3155/redact-db-server
branch
from
September 18, 2026 20:23
b18abbd to
04b53bc
Compare
keelerm84
marked this pull request as ready for review
September 18, 2026 20:32
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 04b53bc. Configure here.
keelerm84
added a commit
that referenced
this pull request
Sep 21, 2026
url.Parse rejects "127.0.0.1:8500" and "[::1]:8500": the first path segment cannot contain a colon, and a digit or "[" cannot begin a scheme. RedactURL treated any parse failure as "could be hiding a credential, replace it whole", so Consul's address -- whose default is exactly 127.0.0.1:8500 -- was reported in the status resource and the startup log as xxxxx, losing an address that holds no credential at all. Only a letter-starting host takes the scheme-plus-opaque path that parses, so the existing cases, consul.example.com:8500 and my-host, could not cover this. A value url.Parse rejects is now replaced whole only when it contains "@", "?" or "#". Those introduce the only components this function redacts: userinfo, a query, and a fragment. A value with none of them is a scheme, host, port and path, all of which are preserved when they do parse, so preserving them here is the same decision rather than a weaker one. Reported by Cursor Bugbot on #879. Its account of the mechanism described url.URL.String inserting a "./" prefix, which is what happens to a relative path containing a colon; this input does not reach String at all, because Parse refuses it first. The conclusion was right either way.
…ver field RedactURL only replaced a password inside a URL's userinfo, and returned an unparseable URL verbatim. ConfigureDataStore then published the Consul host and the DynamoDB endpoint URL into DBServer without redacting either. The status resource is unauthenticated, so a secret in the username position, in a query parameter, or in a fragment was exposed. RedactURL now replaces the userinfo, query and fragment independently, each only when present, and replaces a URL entirely when it cannot be parsed. It handles the non-hierarchical "scheme:rest" shape, whose userinfo lands in URL.Opaque, and preserves a bare "host:port" so Consul's address keeps its port. The scheme, host, port and path survive so the result stays useful for diagnostics. The path is deliberately preserved, so the result is not safe for a URL that embeds a credential in a path segment. docs/endpoints.md states that limitation. The Consul store still receives the real address; only the displayed copy is redacted.
url.Parse rejects "127.0.0.1:8500" and "[::1]:8500": the first path segment cannot contain a colon, and a digit or "[" cannot begin a scheme. RedactURL treated any parse failure as "could be hiding a credential, replace it whole", so Consul's address -- whose default is exactly 127.0.0.1:8500 -- was reported in the status resource and the startup log as xxxxx, losing an address that holds no credential at all. Only a letter-starting host takes the scheme-plus-opaque path that parses, so the existing cases, consul.example.com:8500 and my-host, could not cover this. A value url.Parse rejects is now replaced whole only when it contains "@", "?" or "#". Those introduce the only components this function redacts: userinfo, a query, and a fragment. A value with none of them is a scheme, host, port and path, all of which are preserved when they do parse, so preserving them here is the same decision rather than a weaker one. Reported by Cursor Bugbot on #879. Its account of the mechanism described url.URL.String inserting a "./" prefix, which is what happens to a relative path containing a colon; this input does not reach String at all, because Parse refuses it first. The conclusion was right either way.
keelerm84
force-pushed
the
mk/SDK-3155/redact-db-server
branch
from
September 21, 2026 19:07
9e6b75f to
3e58558
Compare
joker23
approved these changes
Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
util.RedactURLonly replaced a password inside a URL's userinfo, and returned an unparseable URL verbatim.ConfigureDataStorethen published the Consul host and the DynamoDB endpoint URL intoDBServerwithout redacting either. The status resource is unauthenticated, so a secret in the username position, in a query parameter, or in a fragment was exposed.RedactURLnow replaces the userinfo, query and fragment independently, each only when it is present, and replaces a URL entirely when it cannot be parsed. Two shapes needed care:scheme:restURL keeps everything, userinfo included, inURL.Opaque. The config layer accepts these, sinceurl.IsAbsis true, so a missing//must not publish the credential verbatim. Only the part up to the last@is redacted.url.Parsealso reports a barehost:portas a scheme plus an opaque body, and Consul'sdbServeris exactly that shape, so redacting the whole opaque body would destroy the port.The scheme, host, port and path survive so the result stays useful for diagnostics. The path is deliberately preserved, which means the result is not safe for a URL that embeds a credential in a path segment;
docs/endpoints.mdstates that limitation rather than leaving it implied.The Consul store itself still receives the real address. Only the displayed copy is redacted.
This brings
v9to parity withv8#846.Not affected
internal/httpconfig/httpconfig.goredacts its proxy URL withurl.Redacted()directly rather thanutil.RedactURL, so its behavior and its test expectations are unchanged.internal/sdks/big_segments.gois a thirdRedactURLcaller that benefits automatically; it had no redaction assertions to update.integrationtests/database_params_test.goneeds no change: itsDBServerexpectations use Consul and DynamoDB addresses that carry no credentials, so redaction is a no-op there.Note
Overview
Strengthens URL redaction so secrets are not exposed on the unauthenticated
/statusdataStoreStatus.dbServerfield (and related logs).util.RedactURLnow replaces userinfo, query, and fragment withxxxxx(not only passwords), handles unparseable URLs and scheme:opaque shapes, and keeps host/port/path for diagnostics—with a documented exception that path segments are not redacted.ConfigureDataStoreapplies this to Consul hosts and DynamoDB endpoint URLs in status info and Info logs; Redis expectations/tests now cover username-only secrets and query/fragment redaction. Docs describe the redaction rules fordbServer.Reviewed by Cursor Bugbot for commit 3e58558. Bugbot is set up for automated code reviews on this repo. Configure here.