diff options
Diffstat (limited to 'meta/recipes-devtools/go/go/CVE-2025-4674.patch')
-rw-r--r-- | meta/recipes-devtools/go/go/CVE-2025-4674.patch | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go/CVE-2025-4674.patch b/meta/recipes-devtools/go/go/CVE-2025-4674.patch new file mode 100644 index 0000000000..bc6e438652 --- /dev/null +++ b/meta/recipes-devtools/go/go/CVE-2025-4674.patch | |||
@@ -0,0 +1,332 @@ | |||
1 | From e9d2c032b14c17083be0f8f0c822565199d2994f Mon Sep 17 00:00:00 2001 | ||
2 | From: Roland Shoemaker <bracewell@google.com> | ||
3 | Date: Mon, 9 Jun 2025 11:23:46 -0700 | ||
4 | Subject: [PATCH] [release-branch.go1.23] cmd/go: disable support for multiple | ||
5 | vcs in one module | ||
6 | |||
7 | Removes the somewhat redundant vcs.FromDir, "allowNesting" argument, | ||
8 | which was always enabled, and disallow multiple VCS metadata folders | ||
9 | being present in a single directory. This makes VCS injection attacks | ||
10 | much more difficult. | ||
11 | |||
12 | Also adds a GODEBUG, allowmultiplevcs, which re-enables this behavior. | ||
13 | |||
14 | Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc for | ||
15 | reporting this issue. | ||
16 | |||
17 | Updates #74380 | ||
18 | Fixes #74382 | ||
19 | Fixes CVE-2025-4674 | ||
20 | |||
21 | CVE: CVE-2025-4674 | ||
22 | |||
23 | Upstream-Status: Backport [https://github.com/golang/go/commit/e9d2c032b14c17083be0f8f0c822565199d2994f] | ||
24 | |||
25 | Change-Id: I2db79f2baacfacfec331ee7c6978c4057d483eba | ||
26 | Reviewed-on: https://go-review.googlesource.com/c/go/+/686337 | ||
27 | LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> | ||
28 | Reviewed-by: David Chase <drchase@google.com> | ||
29 | Reviewed-by: Carlos Amedee <carlos@golang.org> | ||
30 | Commit-Queue: Carlos Amedee <carlos@golang.org> | ||
31 | |||
32 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
33 | --- | ||
34 | doc/godebug.md | 4 ++ | ||
35 | src/cmd/go/internal/load/pkg.go | 14 ++--- | ||
36 | src/cmd/go/internal/vcs/vcs.go | 28 ++++++---- | ||
37 | src/cmd/go/internal/vcs/vcs_test.go | 2 +- | ||
38 | src/cmd/go/testdata/script/test_multivcs.txt | 54 +++++++++++++++++++ | ||
39 | .../script/version_buildvcs_nested.txt | 20 +++++-- | ||
40 | src/internal/godebugs/godebugs_test.go | 3 +- | ||
41 | src/internal/godebugs/table.go | 1 + | ||
42 | src/runtime/metrics/doc.go | 5 ++ | ||
43 | 9 files changed, 108 insertions(+), 23 deletions(-) | ||
44 | create mode 100644 src/cmd/go/testdata/script/test_multivcs.txt | ||
45 | |||
46 | diff --git a/doc/godebug.md b/doc/godebug.md | ||
47 | index fb3f32f..ae4f057 100644 | ||
48 | --- a/doc/godebug.md | ||
49 | +++ b/doc/godebug.md | ||
50 | @@ -126,6 +126,10 @@ for example, | ||
51 | see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables) | ||
52 | and the [go command documentation](/cmd/go#hdr-Build_and_test_caching). | ||
53 | |||
54 | +Go 1.23.11 disabled build information stamping when multiple VCS are detected due | ||
55 | +to concerns around VCS injection attacks. This behavior can be renabled with the | ||
56 | +setting `allowmultiplevcs=1`. | ||
57 | + | ||
58 | ### Go 1.22 | ||
59 | |||
60 | Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size | ||
61 | diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go | ||
62 | index f41fb2c..428780e 100644 | ||
63 | --- a/src/cmd/go/internal/load/pkg.go | ||
64 | +++ b/src/cmd/go/internal/load/pkg.go | ||
65 | @@ -2465,7 +2465,6 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) { | ||
66 | var repoDir string | ||
67 | var vcsCmd *vcs.Cmd | ||
68 | var err error | ||
69 | - const allowNesting = true | ||
70 | |||
71 | wantVCS := false | ||
72 | switch cfg.BuildBuildvcs { | ||
73 | @@ -2485,7 +2484,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) { | ||
74 | // (so the bootstrap toolchain packages don't even appear to be in GOROOT). | ||
75 | goto omitVCS | ||
76 | } | ||
77 | - repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting) | ||
78 | + repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "") | ||
79 | if err != nil && !errors.Is(err, os.ErrNotExist) { | ||
80 | setVCSError(err) | ||
81 | return | ||
82 | @@ -2508,10 +2507,11 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) { | ||
83 | } | ||
84 | if repoDir != "" && vcsCmd.Status != nil { | ||
85 | // Check that the current directory, package, and module are in the same | ||
86 | - // repository. vcs.FromDir allows nested Git repositories, but nesting | ||
87 | - // is not allowed for other VCS tools. The current directory may be outside | ||
88 | - // p.Module.Dir when a workspace is used. | ||
89 | - pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting) | ||
90 | + // repository. vcs.FromDir disallows nested VCS and multiple VCS in the | ||
91 | + // same repository, unless the GODEBUG allowmultiplevcs is set. The | ||
92 | + // current directory may be outside p.Module.Dir when a workspace is | ||
93 | + // used. | ||
94 | + pkgRepoDir, _, err := vcs.FromDir(p.Dir, "") | ||
95 | if err != nil { | ||
96 | setVCSError(err) | ||
97 | return | ||
98 | @@ -2523,7 +2523,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) { | ||
99 | } | ||
100 | goto omitVCS | ||
101 | } | ||
102 | - modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting) | ||
103 | + modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "") | ||
104 | if err != nil { | ||
105 | setVCSError(err) | ||
106 | return | ||
107 | diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go | ||
108 | index 8550f2a..89d9f0e 100644 | ||
109 | --- a/src/cmd/go/internal/vcs/vcs.go | ||
110 | +++ b/src/cmd/go/internal/vcs/vcs.go | ||
111 | @@ -8,6 +8,7 @@ import ( | ||
112 | "bytes" | ||
113 | "errors" | ||
114 | "fmt" | ||
115 | + "internal/godebug" | ||
116 | "internal/lazyregexp" | ||
117 | "internal/singleflight" | ||
118 | "io/fs" | ||
119 | @@ -831,11 +832,13 @@ type vcsPath struct { | ||
120 | schemelessRepo bool // if true, the repo pattern lacks a scheme | ||
121 | } | ||
122 | |||
123 | +var allowmultiplevcs = godebug.New("allowmultiplevcs") | ||
124 | + | ||
125 | // FromDir inspects dir and its parents to determine the | ||
126 | // version control system and code repository to use. | ||
127 | // If no repository is found, FromDir returns an error | ||
128 | // equivalent to os.ErrNotExist. | ||
129 | -func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) { | ||
130 | +func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) { | ||
131 | // Clean and double-check that dir is in (a subdirectory of) srcRoot. | ||
132 | dir = filepath.Clean(dir) | ||
133 | if srcRoot != "" { | ||
134 | @@ -849,21 +852,28 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm | ||
135 | for len(dir) > len(srcRoot) { | ||
136 | for _, vcs := range vcsList { | ||
137 | if isVCSRoot(dir, vcs.RootNames) { | ||
138 | - // Record first VCS we find. | ||
139 | - // If allowNesting is false (as it is in GOPATH), keep looking for | ||
140 | - // repositories in parent directories and report an error if one is | ||
141 | - // found to mitigate VCS injection attacks. | ||
142 | if vcsCmd == nil { | ||
143 | + // Record first VCS we find. | ||
144 | vcsCmd = vcs | ||
145 | repoDir = dir | ||
146 | - if allowNesting { | ||
147 | + if allowmultiplevcs.Value() == "1" { | ||
148 | + allowmultiplevcs.IncNonDefault() | ||
149 | return repoDir, vcsCmd, nil | ||
150 | } | ||
151 | + // If allowmultiplevcs is not set, keep looking for | ||
152 | + // repositories in current and parent directories and report | ||
153 | + // an error if one is found to mitigate VCS injection | ||
154 | + // attacks. | ||
155 | + continue | ||
156 | + } | ||
157 | + if vcsCmd == vcsGit && vcs == vcsGit { | ||
158 | + // Nested Git is allowed, as this is how things like | ||
159 | + // submodules work. Git explicitly protects against | ||
160 | + // injection against itself. | ||
161 | continue | ||
162 | } | ||
163 | - // Otherwise, we have one VCS inside a different VCS. | ||
164 | - return "", nil, fmt.Errorf("directory %q uses %s, but parent %q uses %s", | ||
165 | - repoDir, vcsCmd.Cmd, dir, vcs.Cmd) | ||
166 | + return "", nil, fmt.Errorf("multiple VCS detected: %s in %q, and %s in %q", | ||
167 | + vcsCmd.Cmd, repoDir, vcs.Cmd, dir) | ||
168 | } | ||
169 | } | ||
170 | |||
171 | diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go | ||
172 | index 2ce85ea..06e63c2 100644 | ||
173 | --- a/src/cmd/go/internal/vcs/vcs_test.go | ||
174 | +++ b/src/cmd/go/internal/vcs/vcs_test.go | ||
175 | @@ -239,7 +239,7 @@ func TestFromDir(t *testing.T) { | ||
176 | } | ||
177 | |||
178 | wantRepoDir := filepath.Dir(dir) | ||
179 | - gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false) | ||
180 | + gotRepoDir, gotVCS, err := FromDir(dir, tempDir) | ||
181 | if err != nil { | ||
182 | t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) | ||
183 | continue | ||
184 | diff --git a/src/cmd/go/testdata/script/test_multivcs.txt b/src/cmd/go/testdata/script/test_multivcs.txt | ||
185 | new file mode 100644 | ||
186 | index 0000000..538cbf7 | ||
187 | --- /dev/null | ||
188 | +++ b/src/cmd/go/testdata/script/test_multivcs.txt | ||
189 | @@ -0,0 +1,54 @@ | ||
190 | +# To avoid VCS injection attacks, we should not accept multiple different VCS metadata | ||
191 | +# folders within a single module (either in the same directory, or nested in different | ||
192 | +# directories.) | ||
193 | +# | ||
194 | +# This behavior should be disabled by setting the allowmultiplevcs GODEBUG. | ||
195 | + | ||
196 | +[short] skip | ||
197 | +[!git] skip | ||
198 | + | ||
199 | +cd samedir | ||
200 | + | ||
201 | +exec git init . | ||
202 | + | ||
203 | +# Without explicitly requesting buildvcs, the go command should silently continue | ||
204 | +# without determining the correct VCS. | ||
205 | +go test -c -o $devnull . | ||
206 | + | ||
207 | +# If buildvcs is explicitly requested, we expect the go command to fail | ||
208 | +! go test -buildvcs -c -o $devnull . | ||
209 | +stderr '^error obtaining VCS status: multiple VCS detected:' | ||
210 | + | ||
211 | +env GODEBUG=allowmultiplevcs=1 | ||
212 | +go test -buildvcs -c -o $devnull . | ||
213 | + | ||
214 | +env GODEBUG= | ||
215 | +cd ../nested | ||
216 | +exec git init . | ||
217 | +# cd a | ||
218 | +go test -c -o $devnull ./a | ||
219 | +! go test -buildvcs -c -o $devnull ./a | ||
220 | +stderr '^error obtaining VCS status: multiple VCS detected:' | ||
221 | +# allowmultiplevcs doesn't disable the check that the current directory, package, and | ||
222 | +# module are in the same repository. | ||
223 | +env GODEBUG=allowmultiplevcs=1 | ||
224 | +! go test -buildvcs -c -o $devnull ./a | ||
225 | +stderr '^error obtaining VCS status: main package is in repository' | ||
226 | + | ||
227 | +-- samedir/go.mod -- | ||
228 | +module example | ||
229 | + | ||
230 | +go 1.18 | ||
231 | +-- samedir/example.go -- | ||
232 | +package main | ||
233 | +-- samedir/.bzr/test -- | ||
234 | +hello | ||
235 | + | ||
236 | +-- nested/go.mod -- | ||
237 | +module example | ||
238 | + | ||
239 | +go 1.18 | ||
240 | +-- nested/a/example.go -- | ||
241 | +package main | ||
242 | +-- nested/a/.bzr/test -- | ||
243 | +hello | ||
244 | diff --git a/src/cmd/go/testdata/script/version_buildvcs_nested.txt b/src/cmd/go/testdata/script/version_buildvcs_nested.txt | ||
245 | index 6dab847..22cd71c 100644 | ||
246 | --- a/src/cmd/go/testdata/script/version_buildvcs_nested.txt | ||
247 | +++ b/src/cmd/go/testdata/script/version_buildvcs_nested.txt | ||
248 | @@ -9,25 +9,35 @@ cd root | ||
249 | go mod init example.com/root | ||
250 | exec git init | ||
251 | |||
252 | -# Nesting repositories in parent directories are ignored, as the current | ||
253 | -# directory main package, and containing main module are in the same repository. | ||
254 | -# This is an error in GOPATH mode (to prevent VCS injection), but for modules, | ||
255 | -# we assume users have control over repositories they've checked out. | ||
256 | + | ||
257 | +# Nesting repositories in parent directories are an error, to prevent VCS injection. | ||
258 | +# This can be disabled with the allowmultiplevcs GODEBUG. | ||
259 | mkdir hgsub | ||
260 | cd hgsub | ||
261 | exec hg init | ||
262 | cp ../../main.go main.go | ||
263 | ! go build | ||
264 | +stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$' | ||
265 | +stderr '^\tUse -buildvcs=false to disable VCS stamping.$' | ||
266 | +env GODEBUG=allowmultiplevcs=1 | ||
267 | +! go build | ||
268 | stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$' | ||
269 | stderr '^\tUse -buildvcs=false to disable VCS stamping.$' | ||
270 | go build -buildvcs=false | ||
271 | +env GODEBUG= | ||
272 | go mod init example.com/root/hgsub | ||
273 | +! go build | ||
274 | +stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$' | ||
275 | +stderr '^\tUse -buildvcs=false to disable VCS stamping.$' | ||
276 | +env GODEBUG=allowmultiplevcs=1 | ||
277 | go build | ||
278 | +env GODEBUG= | ||
279 | cd .. | ||
280 | |||
281 | # It's an error to build a package from a nested Git repository if the package | ||
282 | # is in a separate repository from the current directory or from the module | ||
283 | -# root directory. | ||
284 | +# root directory. Otherwise nested Git repositories are allowed, as this is | ||
285 | +# how Git implements submodules (and protects against Git based VCS injection.) | ||
286 | mkdir gitsub | ||
287 | cd gitsub | ||
288 | exec git init | ||
289 | diff --git a/src/internal/godebugs/godebugs_test.go b/src/internal/godebugs/godebugs_test.go | ||
290 | index a1cb8d4..b3784eb 100644 | ||
291 | --- a/src/internal/godebugs/godebugs_test.go | ||
292 | +++ b/src/internal/godebugs/godebugs_test.go | ||
293 | @@ -39,7 +39,8 @@ func TestAll(t *testing.T) { | ||
294 | if info.Old != "" && info.Changed == 0 { | ||
295 | t.Errorf("Name=%s has Old, missing Changed", info.Name) | ||
296 | } | ||
297 | - if !strings.Contains(doc, "`"+info.Name+"`") { | ||
298 | + if !strings.Contains(doc, "`"+info.Name+"`") && | ||
299 | + !strings.Contains(doc, "`"+info.Name+"=") { | ||
300 | t.Errorf("Name=%s not documented in doc/godebug.md", info.Name) | ||
301 | } | ||
302 | } | ||
303 | diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go | ||
304 | index 11c5b7d..33dcd81 100644 | ||
305 | --- a/src/internal/godebugs/table.go | ||
306 | +++ b/src/internal/godebugs/table.go | ||
307 | @@ -25,6 +25,7 @@ type Info struct { | ||
308 | // Note: After adding entries to this table, update the list in doc/godebug.md as well. | ||
309 | // (Otherwise the test in this package will fail.) | ||
310 | var All = []Info{ | ||
311 | + {Name: "allowmultiplevcs", Package: "cmd/go"}, | ||
312 | {Name: "execerrdot", Package: "os/exec"}, | ||
313 | {Name: "gocachehash", Package: "cmd/go"}, | ||
314 | {Name: "gocachetest", Package: "cmd/go"}, | ||
315 | diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go | ||
316 | index 85f256d..517ec0e 100644 | ||
317 | --- a/src/runtime/metrics/doc.go | ||
318 | +++ b/src/runtime/metrics/doc.go | ||
319 | @@ -230,6 +230,11 @@ Below is the full list of supported metrics, ordered lexicographically. | ||
320 | /gc/stack/starting-size:bytes | ||
321 | The stack size of new goroutines. | ||
322 | |||
323 | + /godebug/non-default-behavior/allowmultiplevcs:events | ||
324 | + The number of non-default behaviors executed by the cmd/go | ||
325 | + package due to a non-default GODEBUG=allowmultiplevcs=... | ||
326 | + setting. | ||
327 | + | ||
328 | /godebug/non-default-behavior/execerrdot:events | ||
329 | The number of non-default behaviors executed by the os/exec | ||
330 | package due to a non-default GODEBUG=execerrdot=... setting. | ||
331 | -- | ||
332 | 2.40.0 | ||