carlos email test: catch a password reaching the logger
Review found a gap: TestStandalonePrintsThePasswordOnce only inspects the io.Writer it was given, so an accidental log.Printf of the password inside printEmailCredentialsCreate would pass every existing test. Add a test that captures the standard logger's own output around the call and asserts the password is absent from it while still present, once, in the intended writer. Confirmed catching: mutating in a log.Printf of the password made this test fail; reverted.
Co-Authored-By: Claude Sonnet 5 (1M context) <noreply@anthropic.com>
1 file changed,
+34
−0
mail_cli_test.go+34 −0
diff --git a/mail_cli_test.go b/mail_cli_test.go| index 0cf1d0a78..fdb593e55 100644 |
| --- a/mail_cli_test.go |
| +++ b/mail_cli_test.go |
| @@ -18,6 +18,7 @@ import ( |
| "encoding/json" |
| "errors" |
| "fmt" |
| + "log" |
| "net/http" |
| "net/http/httptest" |
| "os/exec" |
| @@ -310,6 +311,39 @@ func TestStandalonePrintsThePasswordOnce(t *testing.T) { |
| } |
| } |
| +// TestStandalonePasswordNeverReachesTheLogger closes the gap review found: a |
| +// future accidental `log.Printf` of the password inside |
| +// printEmailCredentialsCreate would pass every existing assertion, because |
| +// TestStandalonePrintsThePasswordOnce only inspects the io.Writer it was |
| +// given, never the standard logger. A credential leaked into a log has no |
| +// revocation story (it is the one door in this whole family that carries a |
| +// secret at all — printEmailCredentialsCreate's own doc comment), so this |
| +// asserts on the ACTUAL password value in BOTH places: present, once, in the |
| +// intended writer, and absent from the logger's own output entirely. |
| +func TestStandalonePasswordNeverReachesTheLogger(t *testing.T) { |
| + var logBuf bytes.Buffer |
| + origOut := log.Writer() |
| + origFlags := log.Flags() |
| + log.SetOutput(&logBuf) |
| + defer func() { |
| + log.SetOutput(origOut) |
| + log.SetFlags(origFlags) |
| + }() |
| + |
| + var out bytes.Buffer |
| + printEmailCredentialsCreate(&out, apiEmailCredsReply{ |
| + App: "seapointish", Name: "laptop", Host: "email-smtp.eu-west-1.amazonaws.com", |
| + Port: "587", Username: "AKIA2", Password: "swordfish-secret", From: "noreply@x.com", |
| + }) |
| + |
| + if n := strings.Count(out.String(), "swordfish-secret"); n != 1 { |
| + t.Fatalf("intended writer: password appears %d times, want exactly 1:\n%s", n, out.String()) |
| + } |
| + if strings.Contains(logBuf.String(), "swordfish-secret") { |
| + t.Fatalf("the password reached the standard logger — a leak with no revocation story:\n%s", logBuf.String()) |
| + } |
| +} |
| + |
| // TestPrintEmailCredentialsListNeverShowsAPassword: the list view reads off |
| // the status reply, whose Standalone entries carry no password field at |
| // all — this pins that the print function does not somehow invent one, and |