Repository navigation
fix(mcp): redact URI userinfo in MCP arguments by reusing the logging helper from #640 - #890
nitininhouse wants to merge 2 commits into
Conversation
bdcf620 to
bc9aa3b
Compare
b4867cc to
ceb3d6d
Compare
|
@claude review |
|
Claude finished @kshivang's task in 4m 10s —— View job Review: redact URI userinfo in MCP arguments
The core call is right. Reusing My findings are all in 1.
|
|
Thanks so much for this contribution, @nitininhouse - the work here is genuinely appreciated, and it's clear real care went into it. This overlaps with #1019 ("test(mcp): state the argument sanitizer's contract as a property, and close the "), which is further along in review and will carry this change forward. To keep review attention focused, I'm closing this one in favor of #1019 - please do review and follow that PR, and you're very welcome to pick up any part of it that still needs help or take on another open issue. Your contribution credit is noted here, and anything unique in this branch that #1019 misses is still welcome as a follow-up. Thanks again for contributing to BossConsole! |
📋 Pull Request
Description
Fixes #886. Follow-up to #837, on
dev.#640 added
LogSanitizer.redactUrlUserInfoand used it to redact URI credentials before logging.McpArgumentSanitizeris a separate sanitizer and never picked it up, so the same password ishidden in a log entry and visible in the MCP ledger:
A credential in a URI authority has no sensitive key name, no assignment and no recognisable token
prefix, so none of the existing rules here saw it.
postgres://admin:hunter2@hosthas a colon, butit is not an assignment and
hunter2has no prefix to match on.This calls the helper #640 already added rather than adding a rule of its own:
curl -u user:passis not a URI, so it keeps a small rule of its own. Its(?!//)guard isload-bearing:
redis-cli -utakes a URL, and without it-u redis://cache.example.invalid:6379matches with
redisas the user and the rest as the secret, blanking a line that holds nocredential at all.
Why reuse rather than a local rule
I wrote a local regex first, and it was worse in a way worth recording. A password containing an
@is ordinary, and stopping at the first@leaves its tail behind:#640's implementation already ends the authority at the first
/,?or#and treats the LAST@in it as the delimiter, which its own KDoc calls out. A second implementation here would be asecond dialect of URI parsing to keep in step, for no benefit. The source carries a comment saying
so, so it does not get quietly reintroduced.
Behaviour note
The helper masks the whole userinfo, so the approval dialog shows
postgres://[REDACTED]@prod-dbrather than keeping the username visible. That matches the logging path, and one convention seems
better than two. Say the word if you would rather the MCP surface keep the user.
Validation
McpArgumentSanitizerUriCredentialTest, 9 tests. Three exist because of specific mistakes:@is removed whole, tail included (the case above)redis-cli -u redis://cache.example.invalid:6379is left alone, so a URI with a port and nocredentials is not read as user
cacheand password6379https://api.example.invalid/a:b@c/dis left alone, since a colon and an@in a path arenot userinfo
The rest pin that every common scheme is covered, that an ordinary URL is untouched, that the host
stays readable, that redaction stops at the end of a line, and that the behaviour merged in #837
still holds.
Sample hosts are RFC 2606
.invaliddomains on purpose. A fixture shaped like a real provider hosttrips GitHub secret scanning on every clone and fork, even with a fabricated credential.
Full
:composeApp:desktopTest --tests "ai.rever.boss.mcp.*"and:composeApp:ktlintCheckgreenlocally. Environment: macOS 15.3 arm64, JDK 17.0.20.1 (Temurin), Gradle 9.7.1.
Deliberately out of scope
#886 also records AWS
AKIA…keys and PEM private key blocks going through unmasked. Those extendcredentialShapePatternrather than reusing a URI helper, so they are a different mechanism. Happyto follow up separately, or to fold them in if you would rather review one change.
🔄 Type of Change
📦 Version Impact
x.x.+1x.+1.0+1.0.0✅ Testing Checklist
🧪 Local Testing
🖥️ Platform Testing
One call and one regex in common code with no platform-specific behaviour, and the tests are plain
JVM unit tests, so the macOS run should carry across. I do not have Windows or Linux hardware to
confirm that.