T09 · Insecure Skill Coding Practices
- Location
scripts/advisor.sh:374- Finding
Arbitrary Python Code Execution Through Target Role Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/advisor.sh, lines 374-381
Vulnerability Type: User-controlled input interpolated into dynamically generated Python source code
Risk Level: HighVulnerable Code
bash result=$( { echo "$profile" echo "---DATA---" cat "$REF_DIR/roles.json" } | python3 -c " import json, sys stdin_data = sys.stdin.read() parts = stdin_data.split('---DATA---') profile = json.loads(parts[0]) roles_data = json.loads(parts[1]) target_role = profile.get('target', '$target_role')Technical Analysis
The
target_roleshell variable originates from the user-controlledtargetproperty supplied through--profile. It is directly interpolated into the source text passed topython3 -c.Parsing the profile as JSON does not make the value safe for insertion into Python source code. A target containing a single quote, closing parenthesis, Python statements, and a comment marker can terminate the intended string literal and append arbitrary Python code.
For example, a target value shaped like the following benign proof of concept can cause the process to run
id:text '); __import__("os").system("id"); #The generated Python statement becomes equivalent to:
python target_role = profile.get('target', ''); __import__("os").system("id"); #')Python evaluates function arguments before calling the function. Consequently, the injected default expression and subsequent statement are processed even when the profile already contains a
targetproperty. The script does not enforceschemas/input.schema.jsonat runtime and does not escape the value for use as Python source.Attack Path
- An attacker supplies a crafted JSON profile through the
--profileargument. - The profile includes a nonempty
targetstring containing Python syntax that closes the intended string literal. parse_profileverifies only that the inpu ...[truncated 1213 chars]
- An attacker supplies a crafted JSON profile through the
- Remediation
View remediation
Remediation Suggestions
Never interpolate user-controlled values into executable Python source. The target is already present in the parsed profile, so it should be read exclusively as data:
python target_role = profile.get("target", "")Remove the
'$target_role'interpolation from thepython3 -cprogram entirely. If a separate value must be supplied, pass it as a positional argument or through a structured input channel:bash python3 -c ' import json import sys profile = json.loads(sys.stdin.readline()) target_role = profile.get("target", "") 'Additional hardening should include:
- Enforce
schemas/input.schema.jsonbefore processing the profile. - Verify that
target,current_role,location, and every skill are strings of reasonable maximum length. - Keep all untrusted values in JSON, standard input, environment variables, or positional arguments rather than embedding them in code.
- Avoid constructing executable programs with double-quoted shell strings.
- Add regression tests using targets containing single quotes, double quotes, newlines, semicolons, comment markers, backslashes, and Python expressions.
- Run the Skill with least privilege and without unnecessary credentials in its environment.
- Do not suppress Python error output with
2>/dev/nullduring validation or security testing, because suppression can conceal injection attempts and parsing failures.
- Enforce
