TestRedactSlashHidesHamrpassKey: with `logging: true`, every prompt (including `/hamrpass `) is written to .codehamr/log.txt. The log is meant to be easy to share for bug reports, so a key in there is a quiet leak even at 0o600. redactSlash is the seam every dbgWritef on a slash payload routes
(t *testing.T)
| 619 | // easy to share for bug reports, so a key in there is a quiet leak even at 0o600. |
| 620 | // redactSlash is the seam every dbgWritef on a slash payload routes through. |
| 621 | func TestRedactSlashHidesHamrpassKey(t *testing.T) { |
| 622 | cases := map[string]string{ |
| 623 | "/hamrpass hp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 624 | "/hamrpass": "/hamrpass", // no arg, nothing to redact |
| 625 | "/hamrpass ": "/hamrpass ", // trailing space, no key to redact |
| 626 | "/clear": "/clear", // unrelated commands pass through |
| 627 | "/models hamrpass": "/models hamrpass", |
| 628 | "hello /hamrpass key": "hello /hamrpass key", // not at line start = not a hamrpass invocation |
| 629 | // Multi-line / tab-separated: Alt+Enter inserts a literal newline, and |
| 630 | // runSlash's strings.Fields splits on any whitespace, so the key activates. |
| 631 | // redactSlash must tokenise the same way or the key survives in log.txt. |
| 632 | "/hamrpass\nhp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 633 | "/hamrpass\thp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 634 | " /hamrpass hp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 635 | // Case-folded name: /HamrPass doesn't activate the key (dispatch is |
| 636 | // case-sensitive) but submit still routes through redactSlash, so the |
| 637 | // token must not survive into scrollback, recall, history, or log.txt. |
| 638 | "/HamrPass hp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 639 | "/HAMRPASS hp_secret_1234567890abcdef": "/hamrpass <redacted>", |
| 640 | } |
| 641 | for in, want := range cases { |
| 642 | if got := redactSlash(in); got != want { |
| 643 | t.Errorf("redactSlash(%q) = %q, want %q", in, got, want) |
| 644 | } |
| 645 | } |
| 646 | } |
| 647 | |
| 648 | // TestSubmitRedactsHamrpassKeyFromHistoryAndScroll: redactSlash keeps the bearer |
| 649 | // token out of the debug log, but submit must also keep it out of scrollback |
nothing calls this directly
no test coverage detected