T09 · Insecure Skill Coding Practices
- Location
scripts/validate-okr.sh:21- Finding
Arbitrary Python Code Execution Through Crafted OKR Filename
- Content
View full analysis
Vulnerability Details
File Location:
scripts/validate-okr.sh, lines 21–29
Vulnerability Type: Python source injection through unsafe filename interpolation
Risk Level: HighVulnerable Code
bash for f in "$OKR_DIR"/*.yaml "$OKR_DIR"/*.yml; do [ -f "$f" ] || continue fname=$(basename "$f") ISSUES=$(python3 -c " import yaml, sys with open('$f') as fh: try:Technical Analysis
The path stored in
$fis expanded directly into source code supplied topython3 -c. Although the shell variable is inside a double-quoted shell string, its value is placed inside a single-quoted Python string literal:python with open('$f') as fh:Shell quoting does not protect the generated Python program from Python-language injection. A filename may legally contain single quotes, parentheses, operators, and other characters that alter the resulting Python expression.
For example, a filename can terminate the original string and append an expression that invokes
__import__()and executes a system command while Python evaluates the argument passed toopen(). Command execution occurs beforeopen()attempts to access the resulting path, so the eventual failure to open that path does not prevent payload execution.The YAML file contents do not need to contain malicious Python; the filename itself is the injection channel.
Attack Path
- An attacker obtains the ability to add or commit a file under the expected
docs/agent-okrdirectory. - The attacker gives a
.yamlor.ymlfile a crafted name containing a single quote and a Python expression. - A user, automated agent, or CI process invokes
scripts/validate-okr.sh. - The shell expands the glob and stores the attacker-controlled path in
$f. $fis interpolated into the program passed topython3 -c.- Python parses the crafted filename as part of its source code and evaluates the injected expression.
- The injected command executes with the privileges ...[truncated 684 chars]
- An attacker obtains the ability to add or commit a file under the expected
- Remediation
View remediation
Remediation Suggestions
Never interpolate a filesystem path into executable Python source. Pass the path as a positional argument and use a quoted heredoc so that shell expansion cannot modify the Python program:
bash ISSUES=$(python3 - "$f" <<'PY' import sys import yaml path = sys.argv[1] with open(path, encoding="utf-8") as fh: try: d = yaml.safe_load(fh) except yaml.YAMLError as exc: print(f"ERRORS:YAML parsing failed: {exc}") sys.exit(0) # Continue validation here. PY )Additional hardening measures should include:
- Keep the heredoc delimiter single-quoted to disable shell interpolation.
- Treat all discovered paths as untrusted input, even when they originate in the repository.
- Run the validator with minimum necessary filesystem and CI permissions.
- Add a regression test using filenames containing quotes, spaces, newlines, and Python metacharacters.
- Consider implementing the complete directory scan in Python using
pathlib, eliminating cross-language string construction.
