From a5c1cd08b372af65ae1e322f814704f8a9821f4d Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Fri, 8 Aug 2025 19:50:19 +0000 Subject: [PATCH 1/2] Patch golang for CVE-2025-47906 --- SPECS/golang/CVE-2025-47906.patch | 183 ++++++++++++++++++++++++++++++ SPECS/golang/golang.spec | 7 +- 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 SPECS/golang/CVE-2025-47906.patch diff --git a/SPECS/golang/CVE-2025-47906.patch b/SPECS/golang/CVE-2025-47906.patch new file mode 100644 index 00000000000..48917da74c1 --- /dev/null +++ b/SPECS/golang/CVE-2025-47906.patch @@ -0,0 +1,183 @@ +From 3d0a24c57c8a16cea02a02ca8498f4645d93737f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Olivier=20Mengu=C3=A9?= +Date: Mon, 30 Jun 2025 16:58:59 +0200 +Subject: [PATCH] os/exec: fix incorrect expansion of "", "." and ".." in + LookPath + +Fix incorrect expansion of "" and "." when $PATH contains an executable +file or, on Windows, a parent directory of a %PATH% element contains an +file with the same name as the %PATH% element but with one of the +%PATHEXT% extension (ex: C:\utils\bin is in PATH, and C:\utils\bin.exe +exists). + +Fix incorrect expansion of ".." when $PATH contains an element which is +an the concatenation of the path to an executable file (or on Windows +a path that can be expanded to an executable by appending a %PATHEXT% +extension), a path separator and a name. + +"", "." and ".." are now rejected early with ErrNotFound. + +Fixes CVE-2025-47906 +Fixes #74803 + +Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e +Reviewed-on: https://go-review.googlesource.com/c/go/+/685755 +LUCI-TryBot-Result: Go LUCI +Auto-Submit: Damien Neil +Reviewed-by: Roland Shoemaker +Reviewed-by: Damien Neil +(cherry picked from commit e0b07dc22eaab1b003d98ad6d63cdfacc76c5c70) +Reviewed-on: https://go-review.googlesource.com/c/go/+/691855 +Reviewed-by: Michael Knyszek +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://github.com/golang/go/commit/8fa31a2d7d9e60c50a3a94080c097b6e65773f4b.patch +--- + src/os/exec/dot_test.go | 56 +++++++++++++++++++++++++++++++++++++++ + src/os/exec/exec.go | 10 +++++++ + src/os/exec/lp_plan9.go | 4 +++ + src/os/exec/lp_unix.go | 4 +++ + src/os/exec/lp_windows.go | 8 ++++++ + 5 files changed, 82 insertions(+) + +diff --git a/src/os/exec/dot_test.go b/src/os/exec/dot_test.go +index ed4bad2..86e9cbb 100644 +--- a/src/os/exec/dot_test.go ++++ b/src/os/exec/dot_test.go +@@ -178,4 +178,60 @@ func TestLookPath(t *testing.T) { + } + } + }) ++ ++ checker := func(test string) func(t *testing.T) { ++ return func(t *testing.T) { ++ t.Helper() ++ t.Logf("PATH=%s", os.Getenv("PATH")) ++ p, err := LookPath(test) ++ if err == nil { ++ t.Errorf("%q: error expected, got nil", test) ++ } ++ if p != "" { ++ t.Errorf("%q: path returned should be \"\". Got %q", test, p) ++ } ++ } ++ } ++ ++ // Reference behavior for the next test ++ t.Run(pathVar+"=$OTHER2", func(t *testing.T) { ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) ++ ++ // Test the behavior when PATH contains an executable file which is not a directory ++ t.Run(pathVar+"=exe", func(t *testing.T) { ++ // Inject an executable file (not a directory) in PATH. ++ // Use our own binary os.Args[0]. ++ testenv.MustHaveExec(t) ++ exe, err := os.Executable() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ t.Setenv(pathVar, exe) ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) ++ ++ // Test the behavior when PATH contains an executable file which is not a directory ++ t.Run(pathVar+"=exe/xx", func(t *testing.T) { ++ // Inject an executable file (not a directory) in PATH. ++ // Use our own binary os.Args[0]. ++ testenv.MustHaveExec(t) ++ exe, err := os.Executable() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ t.Setenv(pathVar, filepath.Join(exe, "xx")) ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) + } +diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go +index b8ef5a0..2c7f510 100644 +--- a/src/os/exec/exec.go ++++ b/src/os/exec/exec.go +@@ -1310,3 +1310,13 @@ func addCriticalEnv(env []string) []string { + // Code should use errors.Is(err, ErrDot), not err == ErrDot, + // to test whether a returned error err is due to this condition. + var ErrDot = errors.New("cannot run executable found relative to current directory") ++ ++// validateLookPath excludes paths that can't be valid ++// executable names. See issue #74466 and CVE-2025-47906. ++func validateLookPath(s string) error { ++ switch s { ++ case "", ".", "..": ++ return ErrNotFound ++ } ++ return nil ++} +diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go +index dffdbac..39f3d33 100644 +--- a/src/os/exec/lp_plan9.go ++++ b/src/os/exec/lp_plan9.go +@@ -36,6 +36,10 @@ func findExecutable(file string) error { + // As of Go 1.19, LookPath will instead return that path along with an error satisfying + // errors.Is(err, ErrDot). See the package documentation for more details. + func LookPath(file string) (string, error) { ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } ++ + // skip the path lookup for these prefixes + skip := []string{"/", "#", "./", "../"} + +diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go +index 3787132..2543525 100644 +--- a/src/os/exec/lp_unix.go ++++ b/src/os/exec/lp_unix.go +@@ -54,6 +54,10 @@ func LookPath(file string) (string, error) { + // (only bypass the path if file begins with / or ./ or ../) + // but that would not match all the Unix shells. + ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } ++ + if strings.Contains(file, "/") { + err := findExecutable(file) + if err == nil { +diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go +index 698a97c..6b87661 100644 +--- a/src/os/exec/lp_windows.go ++++ b/src/os/exec/lp_windows.go +@@ -68,6 +68,10 @@ func findExecutable(file string, exts []string) (string, error) { + // As of Go 1.19, LookPath will instead return that path along with an error satisfying + // errors.Is(err, ErrDot). See the package documentation for more details. + func LookPath(file string) (string, error) { ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } ++ + return lookPath(file, pathExt()) + } + +@@ -81,6 +85,10 @@ func LookPath(file string) (string, error) { + // "C:\foo\example.com" would be returned as-is even if the + // program is actually "C:\foo\example.com.exe". + func lookExtensions(path, dir string) (string, error) { ++ if err := validateLookPath(path); err != nil { ++ return "", &Error{path, err} ++ } ++ + if filepath.Base(path) == path { + path = "." + string(filepath.Separator) + path + } +-- +2.45.4 + diff --git a/SPECS/golang/golang.spec b/SPECS/golang/golang.spec index 7a830894803..337b0c9aca1 100644 --- a/SPECS/golang/golang.spec +++ b/SPECS/golang/golang.spec @@ -15,7 +15,7 @@ Summary: Go Name: golang Version: 1.22.7 -Release: 4%{?dist} +Release: 5%{?dist} License: BSD-3-Clause Vendor: Microsoft Corporation Distribution: Mariner @@ -30,6 +30,7 @@ Patch1: CVE-2024-45336.patch Patch2: CVE-2024-45341.patch Patch3: CVE-2025-22871.patch Patch4: CVE-2025-22870.patch +Patch5: CVE-2025-47906.patch Obsoletes: %{name} < %{version} Provides: %{name} = %{version} Provides: go = %{version}-%{release} @@ -45,6 +46,7 @@ patch -Np1 --ignore-whitespace < %{PATCH0} mv -v go go-bootstrap %setup -q -n go +%patch 5 -p1 %patch 1 -p1 %patch 2 -p1 %patch 3 -p1 @@ -164,6 +166,9 @@ fi %{_bindir}/* %changelog +* Fri Aug 08 2025 Azure Linux Security Servicing Account - 1.22.7-5 +- Patch for CVE-2025-47906 + * Thu May 08 2025 Archana Shettigar - 1.22.7-4 - Address CVE-2025-22870 using an upstream patch. From 627b9ed03f157283b2a87dea65ea58a0a7940dcf Mon Sep 17 00:00:00 2001 From: Kanishk Bansal <103916909+Kanishk-Bansal@users.noreply.github.com> Date: Sat, 9 Aug 2025 01:31:39 +0530 Subject: [PATCH 2/2] Update golang.spec --- SPECS/golang/golang.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPECS/golang/golang.spec b/SPECS/golang/golang.spec index 337b0c9aca1..416a47c608b 100644 --- a/SPECS/golang/golang.spec +++ b/SPECS/golang/golang.spec @@ -46,11 +46,11 @@ patch -Np1 --ignore-whitespace < %{PATCH0} mv -v go go-bootstrap %setup -q -n go -%patch 5 -p1 %patch 1 -p1 %patch 2 -p1 %patch 3 -p1 %patch 4 -p1 +%patch 5 -p1 %build # Go 1.22 requires the final point release of Go 1.20 or later for bootstrap.