T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/harden-skill.sh:13
- Finding
- Python Code Injection in the Hardening Workflow<![CDATA[ ## Vulnerability Details **File Location**: `scripts/harden-skill.sh:13-20` **Vulnerability Type**: Python code injection through unsafe string interpolation **Risk Level**: High ### Vulnerable Code ```bash SKILL_NAME="${1:?Usage: harden-skill.sh <skill-name>}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # Find skill in catalog SKILL_INFO=$(python3 -c " import json with open('$PROJECT_DIR/data/skills.json') as f: catalog = json.load(f) for s in catalog['skills']: if s['name'] == '$SKILL_NAME': print(f'{s[\"author\"]}/{s[\"name\"]}') break else: print('NOT_FOUND') ") ``` ### Technical Analysis The shell argument `SKILL_NAME` is interpolated directly into a Python program passed to `python3 -c`. Shell quoting does not make this value safe inside Python source code. An attacker can include quote characters and additional Python syntax in the skill name, terminate the intended string literal, and cause arbitrary Python statements or expressions to run. This exceeds the minimum privileges required to look up a skill name. The script only needs to compare an input string with catalog entries; it does not need to generate executable Python source from that input. ### Attack Path 1. An attacker persuades an operator or automation system to invoke `harden-skill.sh` with a crafted skill name. 2. The crafted value closes the Python string literal in: ```python if s['name'] == '$SKILL_NAME': ``` 3. Additional attacker-controlled Python syntax is interpreted by `python3 -c`. 4. The payload executes with the operating-system privileges of the user running the review workflow. ### Impact Assessment Successful exploitation provides arbitrary local code execution as the review operator. The attacker could read or modify files accessible to that account, alter catalog data, tamper with reviews, access environment variables, or invoke available local commands. No privilege escalation be ...[truncated 150 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Pass the skill name as a positional argument rather than embedding it into Python source: ```bash SKILL_INFO=$(python3 - "$PROJECT_DIR/data/skills.json" "$SKILL_NAME" <<'PY' import json import sys catalog_path = sys.argv[1] skill_name = sys.argv[2] with open(catalog_path, encoding="utf-8") as f: catalog = json.load(f) for skill in catalog.get("skills", []): if skill.get("name") == skill_name: print(f"{skill['author']}/{skill['name']}") break else: print("NOT_FOUND") PY ) ``` - Validate skill names against a conservative allowlist, such as letters, digits, periods, underscores, and hyphens. - Reject names containing control characters, path separators, quotes, or newlines. - Add regression tests using quotes, backslashes, newlines, and Python metacharacters. ]]>
