Repository navigation
Redact tokens, passwords and device codes from credential ToString [patch] - #202
Conversation
…atch] HostingCredential and GitHubDeviceCode are records, and the compiler-generated ToString printed every property, so logging or interpolating one wrote a live GitHub or Azure DevOps token in plain text. Both now override ToString to print Token, Password and DeviceCode as *** when present (blank when absent), keeping Kind, Username, UserCode and VerificationUri for diagnostics. Fixes #169 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Rt1SUkG3bsTZEWbmGirSx3
|
|
In run 37870035724, The diff only overrides I'm re-running the failed job once. If it hangs again, I'll treat it as real and investigate. Generated by Claude Code |



Fixes #169
What changed
HostingCredentialandGitHubDeviceCodeare records, and the compiler-generatedToString()printed every property. Logging a credential, interpolating it into a string, or putting it in an exception message therefore wrote a live GitHub or Azure DevOps token in plain text.HostingCredential.ToString(): printsTokenandPasswordas***when they are set and blank when they aren't, the same way a record prints a null member.KindandUsernameare still shown.GitHubDeviceCode.ToString(): redactsDeviceCode, which is the value the token poll exchanges for a credential.UserCode,VerificationUri,ExpiresInandIntervalare still shown.Redacted.Of: a new internal helper that holds the placeholder, so both types print it the same way.Both types override
ToStringinstead ofPrintMembers. The repo's analyzers report a privatePrintMemberson a sealed record as unused (IDE0051, as an error), even though the compiler calls it. The output format still matches the compiler'sName { A = …, B = … }shape.Equality,
withand the properties themselves are unchanged. The[DebuggerDisplay]the issue lists as optional isn't added: the debugger's summary line already uses the overriddenToString.Tests (
CredentialRedactionTests)Five new tests cover a token credential, a bearer credential, a username/password credential, string interpolation and a device code. Each one asserts that the secret doesn't appear in the output and that the diagnostic fields do. With the two overrides reverted, all 5 fail. With them, the full suite passes (779/779).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Rt1SUkG3bsTZEWbmGirSx3
Generated by Claude Code