T09 · Insecure Skill Coding Practices
- Location
scripts/list-projects.sh:5- Finding
Python Code Injection Through Unsafely Interpolated HOME-Derived Path
- Content
View full analysis
Vulnerability Details
File Location:
scripts/list-projects.sh, lines 5–19
Vulnerability Type: Environment-variable-based Python code injection
Risk Level: Mediumbash PROJECTS_FILE="$HOME/.reasonix/desktop-projects.json" if [ ! -f "$PROJECTS_FILE" ]; then echo "Error: desktop-projects.json was not found. The Reasonix desktop application may not have been run." exit 1 fi python3 -c " import json with open('$PROJECTS_FILE') as f: d = json.load(f) projects = d.get('projects', []) for p in projects: root = p['root'] topic_count = len(p.get('topics', [])) print(f'{root} ({topic_count} topics)') "Technical Analysis
The script constructs
PROJECTS_FILEfrom the process-controlledHOMEenvironment variable and then directly interpolates that value into source code passed topython3 -c.Shell quoting of
"$PROJECTS_FILE"protects the preliminary file test, but it does not make the value safe for insertion into Python source. IfHOMEcontains Python string delimiters and expressions, the resultingpython3 -cprogram can be syntactically altered.For example, an attacker can construct a
HOMEvalue containing a Python expression such as:text /tmp/x'+str(__import__('os').system('ATTACKER_COMMAND'))+'yThis causes the command expression to be evaluated while Python constructs the argument to
open(). The subsequent file operation may fail because the evaluated path differs from the literal path checked by the shell, but the injected operating-system command has already executed.Exploitation requires the attacker to control the environment of the script and create the literal path expected by the preliminary
-fcheck. These prerequisites reduce exploitability, but they do not eliminate the code-execution flaw.Attack Path
- An attacker gains control over the
HOMEenvironment variable supplied tolist-projects.sh, such as th ...[truncated 1146 chars]
- An attacker gains control over the
- Remediation
View remediation
Remediation Suggestions
Do not embed filesystem paths or other environment-derived values into dynamically generated Python source. Pass the path as a positional argument and read it through
sys.argv:bash PROJECTS_FILE="$HOME/.reasonix/desktop-projects.json" if [ ! -f "$PROJECTS_FILE" ]; then echo "Error: desktop-projects.json was not found. The Reasonix desktop application may not have been run." >&2 exit 1 fi python3 - "$PROJECTS_FILE" <<'PY' import json import sys projects_file = sys.argv[1] with open(projects_file, encoding="utf-8") as f: data = json.load(f) for project in data.get("projects", []): root = project["root"] topic_count = len(project.get("topics", [])) print(f"{root} ({topic_count} topics)") PYThis approach keeps the path as data rather than executable Python syntax. The quoted heredoc delimiter also prevents shell expansion inside the Python program.
Additional hardening measures include:
- Validate that
HOMEis an absolute path and is obtained from a trusted execution context. - Reject unexpected control characters, especially newlines and null-like input representations.
- Run the script with the least privileges required.
- Avoid
eval, dynamic source construction, and interpolation of external values into interpreter command strings throughout the skill. - Add a regression test using
HOMEvalues containing quotes, newlines, spaces, and shell or Python metacharacters.
- Validate that
