Repository navigation
fix(pkg,gcp): logging level race, MaskToken short-input leak, registry-lock I/O, GetCredentials RPC #1054
Description
Problem
A code-review pass over the shared pkg/ module and the GCP provider surfaced
several correctness bugs, two of them High severity, that none of the
in-flight PRs (#1012-#1035, #1036-#1049) touch. Grouping them here.
High
-
10-H4 -
Registry.GetProvider/GetAllProviderscall the factory while
holding the registry lock (pkg/provider/registry.go:60-105).
The GCP factory does multi-page network I/O (getDefaultProject->
Projects.List().Pages(...)) when no project ID is configured. Running that
underr.mu.RLock()blocks every other registry reader (and any writer, e.g.
Unregister) for the duration of an arbitrary user-supplied callback that
performs network calls.GetAllProvidersadditionally serializes N providers'
network init under one lock.
Fix: snapshot the factory (and name) under the lock, release it, then call the
factory outside the critical section. -
10-H3 -
gcp.GetCredentialsissues a liveGetProjectRPC
(providers/gcp/provider.go:270-293).
GetCredentialsgates onIsConfigured(), which constructs a
resourcemanagerclient and performs aGetProjectround-trip purely to
report the credential source.DetectAvailableProvidersalready calls
IsConfigured()+ValidateCredentials(), so a follow-onGetCredentials()
triggers a thirdGetProject. Credential introspection (which source) is
conflated with validation (do they work).
Fix: report the source from env/ADC inspection without a network call.
Low / Nit
-
10-L5 -
pkg/logginglevel read/write data race
(pkg/logging/logger.go).defaultLogger.levelis read in every
Debug/Info/...and written bySetLevel/SetLevelValuewith no
synchronization -> a real-racedata race ifSetLevelis called after
goroutines launch (the concurrent fan-out logs from many goroutines).
Fix: store the level in anatomic.Int32. -
10-L6 -
MaskTokenleaks short inputs verbatim
(pkg/common/tokens.go). The function returns inputs of <=8 chars unchanged.
Current callers only pass 64-char hex tokens, but the generic "return
unchanged" branch is a footgun for any future short secret.
Fix: redact short non-empty inputs to(redacted)instead of echoing them. -
10-N4 -
errors.Ismatches purely on type
(pkg/errors/errors.go).errors.Is(specificNotFound, &NotFoundError{ID:"x"})
returns true regardless of struct fields. This is the documented intent
(type-level sentinel matching), but the field-insensitivity is undocumented.
Fix: document the type-level matching contract on eachIsmethod. -
06-N2 -
RedactedDSNduplicates the DSN format string
(internal/database/config.go:171). The redacted variant copies thehost=... port=... user=...format fromDSN; a future field change must be made in two
places. Fix: derive the redacted form from a single source.
Fix
See per-finding fixes above. Each correctness fix gets a regression test
(notably the logging-level data race under -race and the MaskToken
short-input case).
Files
pkg/provider/registry.goproviders/gcp/provider.gopkg/logging/logger.gopkg/common/tokens.gopkg/errors/errors.gointernal/database/config.go
Findings
10-H3, 10-H4, 10-L5, 10-L6, 10-N4, 06-N2.
Activity
cristim commentedon Jul 27, 2026
Verification sweep against
main(101f099fb) on 2026-07-27 finds this already resolved.All six items are fixed: atomic logging level, registry lock, GetCredentials without RPC, MaskToken short-input handling, errors doc, and DSN dedup.
Evidence: commit 43a009c (PR #1076).
Recommending close. Reopen if any of the six sub-items regressed.
cristim commentedon Aug 24, 2026
Already implemented on
main. Closing with evidence rather than scheduling work.Verified against
origin/main(ae1e632cb), spot-checking the findings this issue names:pkg/logging/logger.go:37storeslevel atomic.Int32, with the comment at :32 recording thatSetLevel/SetLevelValueare called at runtime concurrently with reads.MaskTokenshort-input leak:pkg/common/tokens.go:78returns(none)for empty and(redacted)forlen(token) <= 8, only truncating attoken[:8] + "..."above that. A short token can no longer be echoed whole.RedactedDSNdrift:internal/database/config.go:166isreturn c.dsn("*****"), deriving from the same builder as the real DSN rather than re-implementing the layout, so the two cannot diverge.TestRedactedDSN_SharesLayoutWithDSNpins exactly that.The registry-lock finding (factories snapshotted outside the lock,
GetCredentialsdoing zero RPC) and theerrors.Isdocumentation are addressed in the same change,43a009c7e, which carried no closing trailer.If a residual axis remains that this does not cover, please reopen naming it specifically.