Commit 132441b6f5
132441b6f5658d47482dc3c499c428638f4097da
parent: 0cd2b3a8ac
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-29 02:28 UTC
control: webhook add trims a CRLF from the secret; --secret - counts as stdin
Ref #284
Layout: unified · split
internal/control/control_test.go
+2 −1
| @@ -180,7 +180,8 @@ func TestStdinCommandsReadStdin(t *testing.T) { |
| 180 | for _, cmd := range Commands() { |
180 | for _, cmd := range Commands() { |
| 181 | u := cmd.Usage |
181 | u := cmd.Usage |
| 182 | wants := strings.Contains(u, "--file -") || strings.Contains(u, "< ") || |
182 | wants := strings.Contains(u, "--file -") || strings.Contains(u, "< ") || |
| 183 | strings.Contains(u, "stdin") || strings.Contains(u, "--key -") |
183 | strings.Contains(u, "stdin") || strings.Contains(u, "--key -") || |
| |
184 | strings.Contains(u, "--secret -") |
| 184 | if wants && !cmd.ReadsStdin { |
185 | if wants && !cmd.ReadsStdin { |
| 185 | t.Errorf("%s: usage %q reads stdin but ReadsStdin is not set", strings.Join(cmd.Path, " "), u) |
186 | t.Errorf("%s: usage %q reads stdin but ReadsStdin is not set", strings.Join(cmd.Path, " "), u) |
| 186 | } |
187 | } |
internal/control/webhook.go
+1 −1
| @@ -87,7 +87,7 @@ func runWebhookAdd(c *Ctx, args []string) int { |
| 87 | if err != nil { |
87 | if err != nil { |
| 88 | return c.fail(protocol.ExitFailure, "reading secret: %v", err) |
88 | return c.fail(protocol.ExitFailure, "reading secret: %v", err) |
| 89 | } |
89 | } |
| 90 | secret = strings.TrimRight(string(raw), "\n") |
90 | secret = strings.TrimRight(string(raw), "\r\n") |
| 91 | if secret == "" { |
91 | if secret == "" { |
| 92 | return c.fail(protocol.ExitUsage, "no secret on stdin (pipe it: printf %%s SECRET | ... --secret -)") |
92 | return c.fail(protocol.ExitUsage, "no secret on stdin (pipe it: printf %%s SECRET | ... --secret -)") |
| 93 | } |
93 | } |
internal/control/webhook_test.go
+7 −3
| @@ -70,11 +70,15 @@ func TestWebhookAddSecretFromStdin(t *testing.T) { |
| 70 | if msg, code := run("not a secret\n", "webhook", "add", repo.Path(), "http://127.0.0.1/other"); code != protocol.ExitOK { |
70 | if msg, code := run("not a secret\n", "webhook", "add", repo.Path(), "http://127.0.0.1/other"); code != protocol.ExitOK { |
| 71 | t.Fatalf("no secret: exit %d, %q", code, msg) |
71 | t.Fatalf("no secret: exit %d, %q", code, msg) |
| 72 | } |
72 | } |
| |
73 | // A secret from a file with CRLF line endings loses the \r too. |
| |
74 | if msg, code := run("crlf\r\n", "webhook", "add", repo.Path(), "http://127.0.0.1/crlf", "--secret", "-"); code != protocol.ExitOK { |
| |
75 | t.Fatalf("CRLF secret: exit %d, %q", code, msg) |
| |
76 | } |
| 73 | hooks, err := st.ListWebhooks(repo.ID) |
77 | hooks, err := st.ListWebhooks(repo.ID) |
| 74 | if err != nil || len(hooks) != 2 { |
78 | if err != nil || len(hooks) != 3 { |
| 75 | t.Fatalf("hooks: %+v %v", hooks, err) |
79 | t.Fatalf("hooks: %+v %v", hooks, err) |
| 76 | } |
80 | } |
| 77 | if hooks[0].Secret != "s3cret" || hooks[1].Secret != "" { |
81 | if hooks[0].Secret != "s3cret" || hooks[1].Secret != "" || hooks[2].Secret != "crlf" { |
| 78 | t.Fatalf("secrets: %q, %q", hooks[0].Secret, hooks[1].Secret) |
82 | t.Fatalf("secrets: %q, %q, %q", hooks[0].Secret, hooks[1].Secret, hooks[2].Secret) |
| 79 | } |
83 | } |
| 80 | } |
84 | } |