Skip to content

Commit 7c77546

Browse files
[AUTO-CHERRYPICK] [AutoPR- Security] Patch flannel for CVE-2026-32241 [HIGH] - branch 3.0-dev (#16371)
Co-authored-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
1 parent bc53f7f commit 7c77546

File tree

2 files changed

+131
-3
lines changed

2 files changed

+131
-3
lines changed

SPECS/flannel/CVE-2026-32241.patch

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
From bc1e702975a42ffeaba702ea8e59f111557d0d13 Mon Sep 17 00:00:00 2001
2+
From: AllSpark <allspark@microsoft.com>
3+
Date: Mon, 30 Mar 2026 10:06:28 +0000
4+
Subject: [PATCH] Don't use shell invocations in extensions backend. Avoid
5+
potential command injection by invoking commands directly and expanding env
6+
var references without a shell. Also split configured command strings using
7+
strings.Fields and pass env vars explicitly.
8+
9+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
10+
Upstream-reference: AI Backport of https://github.com/flannel-io/flannel/commit/08bc9a4c990ae785d2fcb448f4991b58485cd26a.patch
11+
---
12+
pkg/backend/extension/extension.go | 35 ++++++++++++++++++++--
13+
pkg/backend/extension/extension_network.go | 7 +++--
14+
2 files changed, 38 insertions(+), 4 deletions(-)
15+
16+
diff --git a/pkg/backend/extension/extension.go b/pkg/backend/extension/extension.go
17+
index 111a04b..118a313 100644
18+
--- a/pkg/backend/extension/extension.go
19+
+++ b/pkg/backend/extension/extension.go
20+
@@ -81,7 +81,8 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr
21+
22+
data := []byte{}
23+
if len(n.preStartupCommand) > 0 {
24+
- cmd_output, err := runCmd([]string{}, "", "sh", "-c", n.preStartupCommand)
25+
+ preArgs := strings.Fields(n.preStartupCommand)
26+
+ cmd_output, err := runCmd([]string{}, "", preArgs[0], preArgs[1:]...)
27+
if err != nil {
28+
return nil, fmt.Errorf("failed to run command: %s Err: %v Output: %s", n.preStartupCommand, err, cmd_output)
29+
} else {
30+
@@ -122,13 +123,14 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr
31+
}
32+
33+
if len(n.postStartupCommand) > 0 {
34+
+ postArgs := strings.Fields(n.postStartupCommand)
35+
cmd_output, err := runCmd([]string{
36+
fmt.Sprintf("NETWORK=%s", config.Network),
37+
fmt.Sprintf("SUBNET=%s", lease.Subnet),
38+
fmt.Sprintf("IPV6SUBNET=%s", lease.IPv6Subnet),
39+
fmt.Sprintf("PUBLIC_IP=%s", attrs.PublicIP),
40+
fmt.Sprintf("PUBLIC_IPV6=%s", attrs.PublicIPv6)},
41+
- "", "sh", "-c", n.postStartupCommand)
42+
+ "", postArgs[0], postArgs[1:]...)
43+
if err != nil {
44+
return nil, fmt.Errorf("failed to run command: %s Err: %v Output: %s", n.postStartupCommand, err, cmd_output)
45+
} else {
46+
@@ -141,8 +143,37 @@ func (be *ExtensionBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr
47+
return n, nil
48+
}
49+
50+
+// buildEnvMap merges os.Environ() with the provided env slice into a lookup map.
51+
+func buildEnvMap(env []string) map[string]string {
52+
+ m := make(map[string]string)
53+
+ for _, e := range os.Environ() {
54+
+ k, v, _ := strings.Cut(e, "=")
55+
+ m[k] = v
56+
+ }
57+
+ for _, e := range env {
58+
+ k, v, _ := strings.Cut(e, "=")
59+
+ m[k] = v
60+
+ }
61+
+ return m
62+
+}
63+
+
64+
+// expandVars expands $VAR / ${VAR} references in each string using the provided map.
65+
+// Because exec.Command is used (no shell), the expanded values are passed as literal
66+
+// arguments — shell metacharacters in variable values cannot cause injection.
67+
+func expandVars(envMap map[string]string, args []string) []string {
68+
+ expanded := make([]string, len(args))
69+
+ for i, a := range args {
70+
+ expanded[i] = os.Expand(a, func(key string) string { return envMap[key] })
71+
+ }
72+
+ return expanded
73+
+}
74+
+
75+
// Run a cmd, returning a combined stdout and stderr.
76+
func runCmd(env []string, stdin string, name string, arg ...string) (string, error) {
77+
+ envMap := buildEnvMap(env)
78+
+ expanded := expandVars(envMap, append([]string{name}, arg...))
79+
+ name, arg = expanded[0], expanded[1:]
80+
+
81+
cmd := exec.Command(name, arg...)
82+
cmd.Env = append(os.Environ(), env...)
83+
84+
diff --git a/pkg/backend/extension/extension_network.go b/pkg/backend/extension/extension_network.go
85+
index 009712f..6f561a9 100644
86+
--- a/pkg/backend/extension/extension_network.go
87+
+++ b/pkg/backend/extension/extension_network.go
88+
@@ -21,6 +21,7 @@ import (
89+
"golang.org/x/net/context"
90+
91+
"fmt"
92+
+ "strings"
93+
94+
"github.com/flannel-io/flannel/pkg/backend"
95+
"github.com/flannel-io/flannel/pkg/lease"
96+
@@ -90,11 +91,12 @@ func (n *network) handleSubnetEvents(batch []lease.Event) {
97+
}
98+
}
99+
100+
+ addArgs := strings.Fields(n.subnetAddCommand)
101+
cmd_output, err := runCmd([]string{
102+
fmt.Sprintf("SUBNET=%s", evt.Lease.Subnet),
103+
fmt.Sprintf("PUBLIC_IP=%s", evt.Lease.Attrs.PublicIP)},
104+
backendData,
105+
- "sh", "-c", n.subnetAddCommand)
106+
+ addArgs[0], addArgs[1:]...)
107+
108+
if err != nil {
109+
log.Errorf("failed to run command: %s Err: %v Output: %s", n.subnetAddCommand, err, cmd_output)
110+
@@ -120,11 +122,12 @@ func (n *network) handleSubnetEvents(batch []lease.Event) {
111+
continue
112+
}
113+
}
114+
+ removeArgs := strings.Fields(n.subnetRemoveCommand)
115+
cmd_output, err := runCmd([]string{
116+
fmt.Sprintf("SUBNET=%s", evt.Lease.Subnet),
117+
fmt.Sprintf("PUBLIC_IP=%s", evt.Lease.Attrs.PublicIP)},
118+
backendData,
119+
- "sh", "-c", n.subnetRemoveCommand)
120+
+ removeArgs[0], removeArgs[1:]...)
121+
122+
if err != nil {
123+
log.Errorf("failed to run command: %s Err: %v Output: %s", n.subnetRemoveCommand, err, cmd_output)
124+
--
125+
2.45.4
126+

SPECS/flannel/flannel.spec

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Summary: Simple and easy way to configure a layer 3 network fabric designed for Kubernetes
44
Name: flannel
55
Version: 0.24.2
6-
Release: 25%{?dist}
6+
Release: 26%{?dist}
77
License: ASL 2.0
88
Vendor: Microsoft Corporation
99
Distribution: Azure Linux
@@ -17,6 +17,7 @@ Patch2: CVE-2023-45288.patch
1717
Patch3: CVE-2025-30204.patch
1818
Patch4: CVE-2024-51744.patch
1919
Patch5: CVE-2025-65637.patch
20+
Patch6: CVE-2026-32241.patch
2021
BuildRequires: gcc
2122
BuildRequires: glibc-devel
2223
BuildRequires: glibc-static >= 2.38-19%{?dist}
@@ -53,9 +54,10 @@ install -p -m 755 -t %{buildroot}%{_bindir} ./dist/flanneld
5354
%{_bindir}/flanneld
5455

5556
%changelog
56-
* Wed Mar 25 2026 Aditya Singh <v-aditysing@microsoft.com> - 0.24.2-25
57+
* Mon Mar 30 2026 Aditya Singh <v-aditysing@microsoft.com> - 0.24.2-26
5758
- Bump to rebuild with updated glibc
58-
59+
* Mon Mar 30 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 0.24.2-25
60+
- Patch for CVE-2026-32241
5961
* Thu Jan 22 2026 Kanishk Bansal <kanbansal@microsoft.com> - 0.24.2-24
6062
- Bump to rebuild with updated glibc
6163

0 commit comments

Comments
 (0)