Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions readiness/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,21 @@ var secretPatterns = []struct {
{regexp.MustCompile(`(?i)(authorization:\s*basic\s+)\S+`), `${1}REDACTED`},

// Postgres / pq form: "password=abc123", "passwd=abc123", "pwd=abc123".
// Case-insensitive so "Password=" also redacts.
{regexp.MustCompile(`(?i)(password=)\S+`), `${1}REDACTED`},
{regexp.MustCompile(`(?i)(passwd=)\S+`), `${1}REDACTED`},
{regexp.MustCompile(`(?i)(pwd=)\S+`), `${1}REDACTED`},
// Case-insensitive so "Password=" also redacts. Each pattern accepts
// three value shapes — pq's key-value DSN (https://pkg.go.dev/github.com/lib/pq)
// supports all of them so a customer connection-URL containing a space
// in the password lands in the error message in quoted form:
// bare: password=secret (ends at next whitespace)
// single-quoted: password='complex pass' (may contain spaces)
// double-quoted: password="complex pass" (may contain spaces)
// The plain `\S+` form caught only the bare case + the first non-space
// token of a quoted value, leaving the rest of the secret on the wire.
// 2026-05-31 fix — registry rows in checks_test.go::secretLeakCases
// (pq_*_quoted_*) lock the three shapes in CI; the registry-walk test
// fails closed on any regression to the bare `\S+` form.
{regexp.MustCompile(`(?i)(password=)(?:'[^']*'|"[^"]*"|\S+)`), `${1}REDACTED`},
{regexp.MustCompile(`(?i)(passwd=)(?:'[^']*'|"[^"]*"|\S+)`), `${1}REDACTED`},
{regexp.MustCompile(`(?i)(pwd=)(?:'[^']*'|"[^"]*"|\S+)`), `${1}REDACTED`},

// pq username leak: 'password authentication failed for user "instant"'.
// Treat usernames as semi-sensitive — a leaked user name still gives
Expand Down
10 changes: 10 additions & 0 deletions readiness/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@
{"pq_password_kv", `pq: FATAL: password=topsecret123 invalid`, []string{"topsecret123"}},
{"pq_passwd_kv", `pq: FATAL: passwd=topsecret123 invalid`, []string{"topsecret123"}},
{"pq_pwd_kv", `pq: FATAL: pwd=topsecret123 invalid`, []string{"topsecret123"}},
// pq's key-value DSN supports single- and double-quoted password values
// when the secret contains whitespace. The bare `\S+` form caught only
// the first non-space token, leaving the rest of the secret on the wire.
// 2026-05-31 regression rows — each shape must not leak its content.
{"pq_password_single_quote", `pq: FATAL: password='top secret with space' invalid`, []string{"top secret with space", "secret with"}},
{"pq_password_double_quote", `pq: FATAL: password="top secret with space" invalid`, []string{"top secret with space", "secret with"}},
{"pq_passwd_single_quote", `pq: FATAL: passwd='multi word secret' invalid`, []string{"multi word secret", "word secret"}},
{"pq_passwd_double_quote", `pq: FATAL: passwd="multi word secret" invalid`, []string{"multi word secret", "word secret"}},
{"pq_pwd_single_quote", `pq: FATAL: pwd='abc 123 def' invalid`, []string{"abc 123 def", "123 def"}},
{"pq_pwd_double_quote", `pq: FATAL: pwd="abc 123 def" invalid`, []string{"abc 123 def", "123 def"}},
{"pq_user_double_quote", `pq: password auth failed for user "dbadmin"`, []string{`"dbadmin"`}},
{"pq_user_single_quote", `pq: password auth failed for user 'dbadmin'`, []string{`'dbadmin'`}},
{"url_postgres", `dial postgres://app:p4ssw0rd@db:5432`, []string{"p4ssw0rd", "app:"}},
Expand Down Expand Up @@ -560,7 +570,7 @@
// ---------------------------------------------------------------------

// TestGRPCHealth_NilCheckerIsFailed — symmetric with PingDB/PingRedis.
// A boot-time mis-wire (the provisioner client field is nil) must

Check warning on line 573 in readiness/checks_test.go

View workflow job for this annotation

GitHub Actions / typos

"mis" should be "miss" or "mist".
// surface as a check failure, not a panic in the readiness handler.
func TestGRPCHealth_NilCheckerIsFailed(t *testing.T) {
res := readiness.GRPCHealth(nil, time.Second)(context.Background())
Expand Down
Loading