T09 · Insecure Skill Coding Practices
- Location
scripts/backup_theme_bundle.py:23- Finding
Shell Command Injection Through an Attacker-Controlled OpenClaw Executable Path
- Content
View full analysis
Vulnerability Details
File Location:
scripts/backup_theme_bundle.py, lines 23–26
Vulnerability Type: OS command injection through unsafe shell interpolation
Risk Level: MediumVulnerable Code:
python def resolve_active_install() -> Path: openclaw_bin = run(["bash", "-lc", "which openclaw"]) resolved = run(["bash", "-lc", f'readlink -f "{openclaw_bin}"']) return Path(resolved).resolve().parentTechnical Analysis
The path returned by
which openclawis interpolated directly into a command evaluated bybash -lc. Double quotes do not prevent command substitution or protect against an embedded double quote terminating the quoted argument.An attacker who can influence the process environment, particularly
PATH, can arrange forwhich openclawto return a path containing shell syntax such as command substitution. When that path is inserted into the secondbash -lcinvocation, Bash interprets the embedded syntax instead of treating the complete path as inert data.The shell is unnecessary for both executable discovery and symbolic-link resolution. Passing attacker-influenced data through a shell creates an avoidable command-injection boundary.
Attack Path
- An attacker gains the ability to influence the
PATHused when the helper is launched, such as through a compromised workspace, wrapper script, or manipulated execution environment. - The attacker creates an executable named
openclawunder a directory whose path contains shell-interpreted syntax. - The first command,
which openclaw, returns the attacker-controlled path as text. - The script interpolates that text into
readlink -f "..."and executes it usingbash -lc. - Bash evaluates the injected syntax while processing the command.
- The attacker's command executes with the privileges of the user running the backup helper.
Impact Assessment
Successful exploitation permits arbitrary loca ...[truncated 483 chars]
- An attacker gains the ability to influence the
- Remediation
View remediation
Remediation Suggestions
Eliminate shell execution and resolve the executable using standard-library APIs:
python def resolve_active_install() -> Path: openclaw_bin = shutil.which("openclaw") if openclaw_bin is None: raise FileNotFoundError("openclaw executable was not found in PATH") return Path(openclaw_bin).resolve().parentAdditional hardening measures:
- Remove the generic shell-based
run()function if no other operation requires it. - If subprocesses are necessary, pass arguments as a list without
shell=Trueor a shell interpreter. - Validate that the resolved executable belongs to an expected OpenClaw installation before reading its bundles.
- Consider accepting an explicit installation path so security-sensitive automation does not depend on a mutable
PATH. - Add a regression test using executable paths containing spaces, quotes, dollar signs, and command-substitution characters, confirming that none are interpreted by a shell.
- Remove the generic shell-based
