Bug: Command injection via unsanitized env vars when inline_env=True
Author: themavikCreated Mar 19, 2026Updated Aug 10, 2026
LabelsBugConnection
Bug Description
In fabric/runners.py, when inline_env=True (default since Fabric 3.0), env keys and values are concatenated directly into a shell command string without any escaping. This allows arbitrary command execution via crafted env values.
Code Location
fabric/runners.py, lines ~67-73:
parameters = " ".join(
["{}={}".format(k, v) for k, v in sorted(env.items())]
)
command = "export {} && {}".format(parameters, command)Reproduction
from fabric import Connection
c = Connection("localhost")
c.run("echo hello", env={"X": "a; echo INJECTED #"})
# Executes: export X=a; echo INJECTED # && echo hello
# Output includes "INJECTED" — arbitrary command executedImpact
Any code path that passes user-controlled or untrusted data into the env parameter of run(), sudo(), or local() is vulnerable to shell command injection.
The code itself has a TODO acknowledging this: "escaping, if we can find a FOOLPROOF THIRD PARTY METHOD for doing so!"
Suggested Fix
Use shlex.quote() for both keys and values:
parameters = " ".join(
["{}={}".format(shlex.quote(k), shlex.quote(v)) for k, v in sorted(env.items())]
)Environment
- Observed on latest main branch
- Affects Fabric 3.x with
inline_env=True(default)
Source: fabric/fabric