Skip to content

Commit 75123c6

Browse files
authored
Merge pull request from GHSA-gc89-7gcr-jxqc
provenance: ensure URLs are redacted before written
2 parents e0fa100 + 90be07e commit 75123c6

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

frontend/dockerfile/dockerfile_buildinfo_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func testBuildInfoSources(t *testing.T, sb integration.Sandbox) {
5252
dockerfile := `
5353
FROM alpine:latest@sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300 AS alpine
5454
FROM busybox:latest
55-
ADD https://raw.githubusercontent.com/moby/moby/v20.10.21/README.md /
55+
ADD https://user2:pw2@raw.githubusercontent.com/moby/moby/v20.10.21/README.md /
5656
COPY --from=alpine /bin/busybox /alpine-busybox
5757
`
5858

@@ -93,10 +93,15 @@ COPY --from=alpine /bin/busybox /alpine-busybox
9393
}}
9494
}
9595

96+
expectedURL := strings.Replace(server.URL, "http://", "http://xxxxx:xxxxx@", 1)
97+
require.NotEqual(t, expectedURL, server.URL)
98+
server.URL = strings.Replace(server.URL, "http://", "http://user:pass@", 1)
99+
96100
res, err := f.Solve(sb.Context(), c, client.SolveOpt{
97101
Exports: exports,
98102
FrontendAttrs: map[string]string{
99-
dockerui.DefaultLocalNameContext: server.URL + "/.git#buildinfo",
103+
dockerui.DefaultLocalNameContext: server.URL + "/.git#buildinfo",
104+
dockerui.DefaultLocalNameContext + ":foo": "https://foo:[email protected]/foo.html",
100105
},
101106
}, nil)
102107
require.NoError(t, err)
@@ -110,7 +115,9 @@ COPY --from=alpine /bin/busybox /alpine-busybox
110115
require.NoError(t, err)
111116

112117
require.Contains(t, bi.Attrs, "context")
113-
require.Equal(t, server.URL+"/.git#buildinfo", *bi.Attrs["context"])
118+
require.Equal(t, expectedURL+"/.git#buildinfo", *bi.Attrs["context"])
119+
120+
require.Equal(t, "https://xxxxx:[email protected]/foo.html", *bi.Attrs["context:foo"])
114121

115122
_, isGateway := f.(*gatewayFrontend)
116123

@@ -131,11 +138,11 @@ COPY --from=alpine /bin/busybox /alpine-busybox
131138
assert.NotEmpty(t, sources[1].Pin)
132139

133140
assert.Equal(t, binfotypes.SourceTypeGit, sources[2].Type)
134-
assert.Equal(t, server.URL+"/.git#buildinfo", sources[2].Ref)
141+
assert.Equal(t, expectedURL+"/.git#buildinfo", sources[2].Ref)
135142
assert.NotEmpty(t, sources[2].Pin)
136143

137144
assert.Equal(t, binfotypes.SourceTypeHTTP, sources[3].Type)
138-
assert.Equal(t, "https://raw.githubusercontent.com/moby/moby/v20.10.21/README.md", sources[3].Ref)
145+
assert.Equal(t, "https://xxxxx:xxxxx@raw.githubusercontent.com/moby/moby/v20.10.21/README.md", sources[3].Ref)
139146
assert.Equal(t, "sha256:419455202b0ef97e480d7f8199b26a721a417818bc0e2d106975f74323f25e6c", sources[3].Pin)
140147
}
141148

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ RUN echo "ok" > /foo
7777
"attest:provenance": provReq,
7878
"build-arg:FOO": "bar",
7979
"label:lbl": "abc",
80-
"vcs:source": "https://example.invalid/repo.git",
80+
"vcs:source": "https://user:pass@example.invalid/repo.git",
8181
"vcs:revision": "123456",
8282
"filename": "Dockerfile",
83+
dockerui.DefaultLocalNameContext + ":foo": "https://foo:[email protected]/foo.html",
8384
},
8485
Exports: []client.ExportEntry{
8586
{
@@ -137,30 +138,32 @@ RUN echo "ok" > /foo
137138
require.Equal(t, "gateway.v0", pred.Invocation.Parameters.Frontend)
138139

139140
if mode == "max" || mode == "" {
140-
require.Equal(t, 3, len(args), "%v", args)
141+
require.Equal(t, 4, len(args), "%v", args)
141142
require.True(t, pred.Metadata.Completeness.Parameters)
142143

143144
require.Equal(t, "bar", args["build-arg:FOO"])
144145
require.Equal(t, "abc", args["label:lbl"])
145146
require.Contains(t, args["source"], "buildkit_test/")
146147
} else {
147148
require.False(t, pred.Metadata.Completeness.Parameters)
148-
require.Equal(t, 1, len(args), "%v", args)
149+
require.Equal(t, 2, len(args), "%v", args)
149150
require.Contains(t, args["source"], "buildkit_test/")
150151
}
152+
require.Equal(t, "https://xxxxx:[email protected]/foo.html", args["context:foo"])
151153
} else {
152154
require.Equal(t, "dockerfile.v0", pred.Invocation.Parameters.Frontend)
153155

154156
if mode == "max" || mode == "" {
155-
require.Equal(t, 2, len(args))
157+
require.Equal(t, 3, len(args))
156158
require.True(t, pred.Metadata.Completeness.Parameters)
157159

158160
require.Equal(t, "bar", args["build-arg:FOO"])
159161
require.Equal(t, "abc", args["label:lbl"])
160162
} else {
161163
require.False(t, pred.Metadata.Completeness.Parameters)
162-
require.Equal(t, 0, len(args), "%v", args)
164+
require.Equal(t, 1, len(args), "%v", args)
163165
}
166+
require.Equal(t, "https://xxxxx:[email protected]/foo.html", args["context:foo"])
164167
}
165168

166169
expectedBase := "pkg:docker/busybox@latest?platform=" + url.PathEscape(platforms.Format(platforms.Normalize(platforms.DefaultSpec())))
@@ -177,7 +180,7 @@ RUN echo "ok" > /foo
177180

178181
if !isClient {
179182
require.Equal(t, "Dockerfile", pred.Invocation.ConfigSource.EntryPoint)
180-
require.Equal(t, "https://example.invalid/repo.git", pred.Metadata.BuildKitMetadata.VCS["source"])
183+
require.Equal(t, "https://xxxxx:xxxxx@example.invalid/repo.git", pred.Metadata.BuildKitMetadata.VCS["source"])
181184
require.Equal(t, "123456", pred.Metadata.BuildKitMetadata.VCS["revision"])
182185
}
183186

@@ -265,6 +268,11 @@ COPY myapp.Dockerfile /
265268

266269
target := registry + "/buildkit/testwithprovenance:git"
267270

271+
// inject dummy credentials to test that they are masked
272+
expectedURL := strings.Replace(server.URL, "http://", "http://xxxxx:xxxxx@", 1)
273+
require.NotEqual(t, expectedURL, server.URL)
274+
server.URL = strings.Replace(server.URL, "http://", "http://user:pass@", 1)
275+
268276
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
269277
FrontendAttrs: map[string]string{
270278
"context": server.URL + "/.git#v1",
@@ -318,7 +326,7 @@ COPY myapp.Dockerfile /
318326
require.Equal(t, "", pred.Invocation.ConfigSource.EntryPoint)
319327
} else {
320328
require.NotEmpty(t, pred.Invocation.Parameters.Frontend)
321-
require.Equal(t, server.URL+"/.git#v1", pred.Invocation.ConfigSource.URI)
329+
require.Equal(t, expectedURL+"/.git#v1", pred.Invocation.ConfigSource.URI)
322330
require.Equal(t, "myapp.Dockerfile", pred.Invocation.ConfigSource.EntryPoint)
323331
}
324332

@@ -332,15 +340,15 @@ COPY myapp.Dockerfile /
332340
require.Equal(t, expBase, pred.Materials[1].URI)
333341
require.NotEmpty(t, pred.Materials[1].Digest["sha256"])
334342

335-
require.Equal(t, server.URL+"/.git#v1", pred.Materials[2].URI)
343+
require.Equal(t, expectedURL+"/.git#v1", pred.Materials[2].URI)
336344
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[2].Digest["sha1"])
337345
} else {
338346
require.Equal(t, 2, len(pred.Materials), "%+v", pred.Materials)
339347

340348
require.Equal(t, expBase, pred.Materials[0].URI)
341349
require.NotEmpty(t, pred.Materials[0].Digest["sha256"])
342350

343-
require.Equal(t, server.URL+"/.git#v1", pred.Materials[1].URI)
351+
require.Equal(t, expectedURL+"/.git#v1", pred.Materials[1].URI)
344352
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[1].Digest["sha1"])
345353
}
346354

solver/llbsolver/provenance/capture.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
distreference "github.com/docker/distribution/reference"
77
"github.com/moby/buildkit/solver/result"
8+
"github.com/moby/buildkit/util/urlutil"
89
digest "github.com/opencontainers/go-digest"
910
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1011
)
@@ -190,6 +191,7 @@ func (c *Capture) AddLocal(l LocalSource) {
190191
}
191192

192193
func (c *Capture) AddGit(g GitSource) {
194+
g.URL = urlutil.RedactCredentials(g.URL)
193195
for _, v := range c.Sources.Git {
194196
if v.URL == g.URL {
195197
return
@@ -199,6 +201,7 @@ func (c *Capture) AddGit(g GitSource) {
199201
}
200202

201203
func (c *Capture) AddHTTP(h HTTPSource) {
204+
h.URL = urlutil.RedactCredentials(h.URL)
202205
for _, v := range c.Sources.HTTP {
203206
if v.URL == h.URL {
204207
return

solver/llbsolver/provenance/predicate.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
88
slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
99
"github.com/moby/buildkit/util/purl"
10+
"github.com/moby/buildkit/util/urlutil"
1011
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1112
"github.com/package-url/packageurl-go"
1213
)
@@ -151,6 +152,7 @@ func NewPredicate(c *Capture) (*ProvenancePredicate, error) {
151152
} else {
152153
inv.ConfigSource.URI = v
153154
}
155+
inv.ConfigSource.URI = urlutil.RedactCredentials(inv.ConfigSource.URI)
154156
delete(c.Args, contextKey)
155157
}
156158

@@ -162,6 +164,9 @@ func NewPredicate(c *Capture) (*ProvenancePredicate, error) {
162164
vcs := make(map[string]string)
163165
for k, v := range c.Args {
164166
if strings.HasPrefix(k, "vcs:") {
167+
if k == "vcs:source" {
168+
v = urlutil.RedactCredentials(v)
169+
}
165170
delete(c.Args, k)
166171
if v != "" {
167172
vcs[strings.TrimPrefix(k, "vcs:")] = v
@@ -231,6 +236,11 @@ func FilterArgs(m map[string]string) map[string]string {
231236
"platform": {},
232237
"cache-imports": {},
233238
}
239+
const defaultContextKey = "context"
240+
contextKey := defaultContextKey
241+
if v, ok := m["contextkey"]; ok && v != "" {
242+
contextKey = v
243+
}
234244
out := make(map[string]string)
235245
for k, v := range m {
236246
if _, ok := hostSpecificArgs[k]; ok {
@@ -239,6 +249,9 @@ func FilterArgs(m map[string]string) map[string]string {
239249
if strings.HasPrefix(k, "attest:") {
240250
continue
241251
}
252+
if k == contextKey || strings.HasPrefix(k, defaultContextKey+":") {
253+
v = urlutil.RedactCredentials(v)
254+
}
242255
out[k] = v
243256
}
244257
return out

0 commit comments

Comments
 (0)