diff --git a/SPECS/flannel/CVE-2026-32241.patch b/SPECS/flannel/CVE-2026-32241.patch new file mode 100644 index 00000000000..c8877b625e5 --- /dev/null +++ b/SPECS/flannel/CVE-2026-32241.patch @@ -0,0 +1,122 @@ +From 08bc9a4c990ae785d2fcb448f4991b58485cd26a Mon Sep 17 00:00:00 2001 +From: Thomas Ferrandiz +Date: Mon, 9 Mar 2026 16:21:04 +0000 +Subject: [PATCH] Don't use shell invocations in extensions backend. + +This avoids potential malicious code injection. + +Upstream Patch reference: https://github.com/flannel-io/flannel/commit/08bc9a4c990ae785d2fcb448f4991b58485cd26a.patch +--- + backend/extension/extension.go | 35 ++++++++++++++++++++++++-- + backend/extension/extension_network.go | 7 ++++-- + 2 files changed, 38 insertions(+), 4 deletions(-) + +diff --git a/backend/extension/extension.go b/backend/extension/extension.go +index 32d51f1..ee1a856 100644 +--- a/backend/extension/extension.go ++++ b/backend/extension/extension.go +@@ -80,7 +80,8 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr + + data := []byte{} + if len(n.preStartupCommand) > 0 { +- cmd_output, err := runCmd([]string{}, "", "sh", "-c", n.preStartupCommand) ++ preArgs := strings.Fields(n.preStartupCommand) ++ cmd_output, err := runCmd([]string{}, "", preArgs[0], preArgs[1:]...) + if err != nil { + return nil, fmt.Errorf("failed to run command: %s Err: %v Output: %s", n.preStartupCommand, err, cmd_output) + } else { +@@ -114,11 +115,12 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr + } + + if len(n.postStartupCommand) > 0 { ++ postArgs := strings.Fields(n.postStartupCommand) + cmd_output, err := runCmd([]string{ + fmt.Sprintf("NETWORK=%s", config.Network), + fmt.Sprintf("SUBNET=%s", lease.Subnet), + fmt.Sprintf("PUBLIC_IP=%s", attrs.PublicIP)}, +- "", "sh", "-c", n.postStartupCommand) ++ "", postArgs[0], postArgs[1:]...) + if err != nil { + return nil, fmt.Errorf("failed to run command: %s Err: %v Output: %s", n.postStartupCommand, err, cmd_output) + } else { +@@ -131,8 +133,37 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr + return n, nil + } + ++// buildEnvMap merges os.Environ() with the provided env slice into a lookup map. ++func buildEnvMap(env []string) map[string]string { ++ m := make(map[string]string) ++ for _, e := range os.Environ() { ++ k, v, _ := strings.Cut(e, "=") ++ m[k] = v ++ } ++ for _, e := range env { ++ k, v, _ := strings.Cut(e, "=") ++ m[k] = v ++ } ++ return m ++} ++ ++// expandVars expands $VAR / ${VAR} references in each string using the provided map. ++// Because exec.Command is used (no shell), the expanded values are passed as literal ++// arguments — shell metacharacters in variable values cannot cause injection. ++func expandVars(envMap map[string]string, args []string) []string { ++ expanded := make([]string, len(args)) ++ for i, a := range args { ++ expanded[i] = os.Expand(a, func(key string) string { return envMap[key] }) ++ } ++ return expanded ++} ++ + // Run a cmd, returning a combined stdout and stderr. + func runCmd(env []string, stdin string, name string, arg ...string) (string, error) { ++ envMap := buildEnvMap(env) ++ expanded := expandVars(envMap, append([]string{name}, arg...)) ++ name, arg = expanded[0], expanded[1:] ++ + cmd := exec.Command(name, arg...) + cmd.Env = append(os.Environ(), env...) + +diff --git a/backend/extension/extension_network.go b/backend/extension/extension_network.go +index 7d75cae4..e639518 100644 +--- a/backend/extension/extension_network.go ++++ b/backend/extension/extension_network.go +@@ -21,6 +21,7 @@ import ( + "golang.org/x/net/context" + + "fmt" ++ "strings" + + "github.com/flannel-io/flannel/backend" + "github.com/flannel-io/flannel/subnet" +@@ -92,11 +93,12 @@ func (n *network) handleSubnetEvents(batch []subnet.Event) { + } + } + ++ addArgs := strings.Fields(n.subnetAddCommand) + cmd_output, err := runCmd([]string{ + fmt.Sprintf("SUBNET=%s", evt.Lease.Subnet), + fmt.Sprintf("PUBLIC_IP=%s", evt.Lease.Attrs.PublicIP)}, + backendData, +- "sh", "-c", n.subnetAddCommand) ++ addArgs[0], addArgs[1:]...) + + if err != nil { + log.Errorf("failed to run command: %s Err: %v Output: %s", n.subnetAddCommand, err, cmd_output) +@@ -122,11 +124,12 @@ func (n *network) handleSubnetEvents(batch []subnet.Event) { + continue + } + } ++ removeArgs := strings.Fields(n.subnetRemoveCommand) + cmd_output, err := runCmd([]string{ + fmt.Sprintf("SUBNET=%s", evt.Lease.Subnet), + fmt.Sprintf("PUBLIC_IP=%s", evt.Lease.Attrs.PublicIP)}, + backendData, +- "sh", "-c", n.subnetRemoveCommand) ++ removeArgs[0], removeArgs[1:]...) + + if err != nil { + log.Errorf("failed to run command: %s Err: %v Output: %s", n.subnetRemoveCommand, err, cmd_output) +-- +2.43.0 + diff --git a/SPECS/flannel/flannel.spec b/SPECS/flannel/flannel.spec index 1415432ba89..361968cac0d 100644 --- a/SPECS/flannel/flannel.spec +++ b/SPECS/flannel/flannel.spec @@ -4,7 +4,7 @@ Summary: Simple and easy way to configure a layer 3 network fabric designed for Kubernetes Name: flannel Version: 0.14.0 -Release: 30%{?dist} +Release: 31%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Mariner @@ -14,6 +14,7 @@ URL: https://github.com/flannel-io/flannel Source0: %{name}-%{version}.tar.gz Patch0: CVE-2021-44716.patch Patch1: CVE-2025-65637.patch +Patch2: CVE-2026-32241.patch BuildRequires: gcc BuildRequires: glibc-devel @@ -50,6 +51,9 @@ install -p -m 755 -t %{buildroot}%{_bindir} ./dist/flanneld %{_bindir}/flanneld %changelog +* Thu Apr 09 2026 Azure Linux Security Servicing Account - 0.14.0-31 +- Patch for CVE-2026-32241 + * Tue Feb 03 2026 Aditya Singh - 0.14.0-30 - Bump to rebuild with updated glibc @@ -95,7 +99,7 @@ install -p -m 755 -t %{buildroot}%{_bindir} ./dist/flanneld * Mon Aug 07 2023 CBL-Mariner Servicing Account - 0.14.0-16 - Bump release to rebuild with go 1.19.12 -* Wed Jul 14 2023 Andrew Phelps - 0.14.0-15 +* Fri Jul 14 2023 Andrew Phelps - 0.14.0-15 - Bump release to rebuild against glibc 2.35-4 * Thu Jul 13 2023 CBL-Mariner Servicing Account - 0.14.0-14