sha256convert: redact credentials from source URL in output and tags · Entire

sha256convert: redact credentials from source URL in output and tags

A source URL can embed credentials (https://user:token@host/...). Those were copied verbatim into the signed attestation tag message — which is permanent and gets pushed — as well as the "fetching ..." status line and the JSON/textual result.

Redact the whole userinfo component (not just the password: token auth often puts the secret in the username position, which url.URL.Redacted() leaves intact) before any of those surfaces. The fetch path keeps the original req.SourceURL, so authentication is unaffected.

Sessions

e8268fe0a082View transcript

Changes

2

259 unmodified lines

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
268
275
276
277
278
38 unmodified lines

317
318
319
313
320
321
322
323
110 unmodified lines

434
435
436
430
437
438
439
440
355 unmodified lines

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

259 unmodified lines

}

func redactSourceURL(raw string) string {
    u, err := url.Parse(raw)
    if err != nil {
        return "<source url redacted>"
    }
    u.User = nil
    return u.String()
}

func TestRedactSourceURL(t *testing.T) { tests := []struct { name string in string want string }{ {"no credentials", "https://github.com/o/r.git", "https://github.com/o/r.git"}, {"user and password", "https://user:secret@github.com/o/r.git", "https://github.com/o/r.git"}, {"token as username", "https://ghp_abc123@github.com/o/r.git", "https://github.com/o/r.git"}, {"x-access-token form", "https://x-access-token:ghp_abc@github.com/o/r.git", "https://github.com/o/r.git"}, {"unparseable", "https://tok@ho%zz/r.git", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := redactSourceURL(tt.in); got != tt.want { t.Errorf("redactSourceURL(%q) = %q, want %q", tt.in, got, tt.want) } }) } }

func TestRun_RejectsExcludePrefixesThatDropBranchesOrTags(t *testing.T) { // We never reach the network here — the validation fires before // any I/O — so a non-empty target dir is the only thing the early