[RANCHER] OS command injection in Rancher and Fleet
Description
CVE-2022-31249 is an OS command injection vulnerability in SUSE Rancher's Wrangler library that allows remote attackers to execute arbitrary commands on the underlying host.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CVE-2022-31249 is an OS command injection vulnerability in SUSE Rancher's Wrangler library that allows remote attackers to execute arbitrary commands on the underlying host.
CVE-2022-31249 describes an Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') vulnerability in the wrangler component of SUSE Rancher. Wrangler is a framework used to implement Kubernetes controllers, and this flaw stems from insufficient sanitization of user-supplied input when constructing operating system commands [1][2].
Exploitation occurs when an attacker provides crafted commands to Wrangler, which are then executed without proper validation. An attacker does not need prior authentication to the wrangler service, making this a remotely exploitable issue if the affected component is network-accessible [2]. The vulnerable versions include wrangler 0.7.3 and prior, 0.8.4 and prior, and 1.0.0 and prior [2].
A successful attack enables remote code execution on the host system where Wrangler is running. This could allow an attacker to escalate privileges, pivot to other systems, or compromise the entire Kubernetes cluster's infrastructure [2].
Patches have been released by the vendor. Security-fix releases are identified as v0.7.4-security1 and v0.8.5-security1 [3][4]. Users should upgrade to these patched versions or later. For Rancher deployments using Wrangler, applying the appropriate update in line with the supported Rancher version (e.g., 2.6.x or 2.7.x) is recommended [1].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/rancher/wranglerGo | < 0.7.4-security1 | 0.7.4-security1 |
github.com/rancher/wranglerGo | >= 0.8.0, < 0.8.5-security1 | 0.8.5-security1 |
github.com/rancher/wranglerGo | >= 1.0.0, < 1.0.1 | 1.0.1 |
github.com/rancher/wranglerGo | >= 0.8.6, < 0.8.11 | 0.8.11 |
Affected products
2Patches
41 file changed · +6 −6
pkg/git/git.go+6 −6 modified@@ -68,7 +68,7 @@ func (g *Git) LsRemote(branch string, commit string) (string, error) { } output := &bytes.Buffer{} - if err := g.gitCmd(output, "ls-remote", g.URL, formatRefForBranch(branch)); err != nil { + if err := g.gitCmd(output, "ls-remote", "--", g.URL, formatRefForBranch(branch)); err != nil { return "", err } @@ -97,9 +97,9 @@ func (g *Git) Head(branch string) (string, error) { // Clone runs git clone with depth 1 func (g *Git) Clone(branch string) error { if branch == "" { - return g.git("clone", "--depth=1", "-n", g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--", g.URL, g.Directory) } - return g.git("clone", "--depth=1", "-n", "--branch", branch, g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--branch="+branch, "--", g.URL, g.Directory) } // Update updates git repo if remote sha has changed @@ -302,22 +302,22 @@ func (g *Git) clone(branch string) error { } func (g *Git) fetchAndReset(rev string) error { - if err := g.git("-C", g.Directory, "fetch", "origin", rev); err != nil { + if err := g.git("-C", g.Directory, "fetch", "origin", "--", rev); err != nil { return err } return g.reset("FETCH_HEAD") } func (g *Git) reset(rev string) error { - return g.git("-C", g.Directory, "reset", "--hard", rev) + return g.git("-C", g.Directory, "reset", "--hard", "--", rev) } func (g *Git) currentCommit() (string, error) { return g.gitOutput("-C", g.Directory, "rev-parse", "HEAD") } func (g *Git) gitCmd(output io.Writer, args ...string) error { - kv := fmt.Sprintf("credential.helper=%s", "/bin/sh -c 'echo password=$GIT_PASSWORD'") + kv := fmt.Sprintf("credential.helper=%s", `/bin/sh -c 'echo "password=$GIT_PASSWORD"'`) cmd := exec.Command("git", append([]string{"-c", kv}, args...)...) cmd.Env = append(os.Environ(), fmt.Sprintf("GIT_PASSWORD=%s", g.password)) stderrBuf := &bytes.Buffer{}
1 file changed · +6 −6
pkg/git/git.go+6 −6 modified@@ -68,7 +68,7 @@ func (g *Git) LsRemote(branch string, commit string) (string, error) { } output := &bytes.Buffer{} - if err := g.gitCmd(output, "ls-remote", g.URL, formatRefForBranch(branch)); err != nil { + if err := g.gitCmd(output, "ls-remote", "--", g.URL, formatRefForBranch(branch)); err != nil { return "", err } @@ -97,9 +97,9 @@ func (g *Git) Head(branch string) (string, error) { // Clone runs git clone with depth 1 func (g *Git) Clone(branch string) error { if branch == "" { - return g.git("clone", "--depth=1", "-n", g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--", g.URL, g.Directory) } - return g.git("clone", "--depth=1", "-n", "--branch", branch, g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--branch="+branch, "--", g.URL, g.Directory) } // Update updates git repo if remote sha has changed @@ -302,22 +302,22 @@ func (g *Git) clone(branch string) error { } func (g *Git) fetchAndReset(rev string) error { - if err := g.git("-C", g.Directory, "fetch", "origin", rev); err != nil { + if err := g.git("-C", g.Directory, "fetch", "origin", "--", rev); err != nil { return err } return g.reset("FETCH_HEAD") } func (g *Git) reset(rev string) error { - return g.git("-C", g.Directory, "reset", "--hard", rev) + return g.git("-C", g.Directory, "reset", "--hard", "--", rev) } func (g *Git) currentCommit() (string, error) { return g.gitOutput("-C", g.Directory, "rev-parse", "HEAD") } func (g *Git) gitCmd(output io.Writer, args ...string) error { - kv := fmt.Sprintf("credential.helper=%s", "/bin/sh -c 'echo password=$GIT_PASSWORD'") + kv := fmt.Sprintf("credential.helper=%s", `/bin/sh -c 'echo "password=$GIT_PASSWORD"'`) cmd := exec.Command("git", append([]string{"-c", kv}, args...)...) cmd.Env = append(os.Environ(), fmt.Sprintf("GIT_PASSWORD=%s", g.password)) stderrBuf := &bytes.Buffer{}
1 file changed · +8 −5
pkg/git/git.go+8 −5 modified@@ -68,7 +68,7 @@ func (g *Git) LsRemote(branch string, commit string) (string, error) { } output := &bytes.Buffer{} - if err := g.gitCmd(output, "ls-remote", g.URL, formatRefForBranch(branch)); err != nil { + if err := g.gitCmd(output, "ls-remote", "--", g.URL, formatRefForBranch(branch)); err != nil { return "", err } @@ -96,7 +96,10 @@ func (g *Git) Head(branch string) (string, error) { // Clone runs git clone with depth 1 func (g *Git) Clone(branch string) error { - return g.git("clone", "--depth=1", "-n", "--branch", branch, g.URL, g.Directory) + if branch == "" { + return g.git("clone", "--depth=1", "-n", "--", g.URL, g.Directory) + } + return g.git("clone", "--depth=1", "-n", "--branch="+branch, "--", g.URL, g.Directory) } // Update updates git repo if remote sha has changed @@ -299,22 +302,22 @@ func (g *Git) clone(branch string) error { } func (g *Git) fetchAndReset(rev string) error { - if err := g.git("-C", g.Directory, "fetch", "origin", rev); err != nil { + if err := g.git("-C", g.Directory, "fetch", "origin", "--", rev); err != nil { return err } return g.reset("FETCH_HEAD") } func (g *Git) reset(rev string) error { - return g.git("-C", g.Directory, "reset", "--hard", rev) + return g.git("-C", g.Directory, "reset", "--hard", "--", rev) } func (g *Git) currentCommit() (string, error) { return g.gitOutput("-C", g.Directory, "rev-parse", "HEAD") } func (g *Git) gitCmd(output io.Writer, args ...string) error { - kv := fmt.Sprintf("credential.helper=%s", "/bin/sh -c 'echo password=$GIT_PASSWORD'") + kv := fmt.Sprintf("credential.helper=%s", `/bin/sh -c 'echo "password=$GIT_PASSWORD"'`) cmd := exec.Command("git", append([]string{"-c", kv}, args...)...) cmd.Env = append(os.Environ(), fmt.Sprintf("GIT_PASSWORD=%s", g.password)) stderrBuf := &bytes.Buffer{}
8649ecc06220Fix up git package
1 file changed · +6 −6
pkg/git/git.go+6 −6 modified@@ -68,7 +68,7 @@ func (g *Git) LsRemote(branch string, commit string) (string, error) { } output := &bytes.Buffer{} - if err := g.gitCmd(output, "ls-remote", g.URL, formatRefForBranch(branch)); err != nil { + if err := g.gitCmd(output, "ls-remote", "--", g.URL, formatRefForBranch(branch)); err != nil { return "", err } @@ -97,9 +97,9 @@ func (g *Git) Head(branch string) (string, error) { // Clone runs git clone with depth 1 func (g *Git) Clone(branch string) error { if branch == "" { - return g.git("clone", "--depth=1", "-n", g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--", g.URL, g.Directory) } - return g.git("clone", "--depth=1", "-n", "--branch", branch, g.URL, g.Directory) + return g.git("clone", "--depth=1", "-n", "--branch="+branch, "--", g.URL, g.Directory) } // Update updates git repo if remote sha has changed @@ -302,22 +302,22 @@ func (g *Git) clone(branch string) error { } func (g *Git) fetchAndReset(rev string) error { - if err := g.git("-C", g.Directory, "fetch", "origin", rev); err != nil { + if err := g.git("-C", g.Directory, "fetch", "origin", "--", rev); err != nil { return err } return g.reset("FETCH_HEAD") } func (g *Git) reset(rev string) error { - return g.git("-C", g.Directory, "reset", "--hard", rev) + return g.git("-C", g.Directory, "reset", "--hard", "--", rev) } func (g *Git) currentCommit() (string, error) { return g.gitOutput("-C", g.Directory, "rev-parse", "HEAD") } func (g *Git) gitCmd(output io.Writer, args ...string) error { - kv := fmt.Sprintf("credential.helper=%s", "/bin/sh -c 'echo password=$GIT_PASSWORD'") + kv := fmt.Sprintf("credential.helper=%s", `/bin/sh -c 'echo "password=$GIT_PASSWORD"'`) cmd := exec.Command("git", append([]string{"-c", kv}, args...)...) cmd.Env = append(os.Environ(), fmt.Sprintf("GIT_PASSWORD=%s", g.password)) stderrBuf := &bytes.Buffer{}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-qrg7-hfx7-95c5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-31249ghsaADVISORY
- bugzilla.suse.com/show_bug.cgighsaWEB
- github.com/rancher/wrangler/commit/12397eec50155cb2d24aa70bdf9e90c5f3b9a727ghsaWEB
- github.com/rancher/wrangler/commit/341018c8fef3e12867c7cb2649bd2cecac75f287ghsaWEB
- github.com/rancher/wrangler/commit/5a387e13e8d51e3340d9e5012a1951f0cca5fc90ghsaWEB
- github.com/rancher/wrangler/commit/8649ecc062204f28764fd80157a621cbae89c9cfghsaWEB
- github.com/rancher/wrangler/compare/v0.7.2...v0.7.4-security1ghsaWEB
- github.com/rancher/wrangler/compare/v0.8.4...v0.8.5-security1ghsaWEB
- github.com/rancher/wrangler/security/advisories/GHSA-qrg7-hfx7-95c5ghsaWEB
- pkg.go.dev/vuln/GO-2023-1519ghsaWEB
News mentions
0No linked articles in our index yet.