T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/emotion_memory.sh:43
- Finding
- Arbitrary Python Code Execution Through Memory Manager Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/emotion_memory.sh:43-50, 57-72, 109-119, 124-137` **Vulnerability Type**: User-controlled data interpolated into dynamically generated Python source **Risk Level**: High ### Vulnerable Code ```bash python3 -c " import json, sys with open('$MEMORY_FILE', 'r') as f: data = json.load(f) entry = json.loads('''$ENTRY''') data['patterns'].append(entry) with open('$MEMORY_FILE', 'w') as f: json.dump(data, f, indent=2) print(f'Stored: {entry[\"id\"]}') " ``` ```bash python3 -c " import json with open('$MEMORY_FILE', 'r') as f: data = json.load(f) query = '$QUERY'.lower() results = [] for p in data['patterns']: if query in p.get('observation','').lower() or any(query in t.lower() for t in p.get('tags',[])): results.append(p) if not results: print('No matching patterns found.') else: for r in results[-10:]: print(f\"[{r['timestamp']}] ({r['importance']}) {r['observation']}\") if r.get('tags'): print(f\" tags: {', '.join(r['tags'])}\") " ``` ```bash python3 -c " import json with open('$MEMORY_FILE', 'r') as f: data = json.load(f) patterns = data.get('patterns', []) for p in patterns[-$LIMIT:]: print(f\"[{p['id']}] {p['timestamp']} ({p['importance']})\") print(f\" {p['observation']}\") if p.get('tags'): print(f\" tags: {', '.join(p['tags'])}\") " ``` ```bash python3 -c " import json with open('$MEMORY_FILE', 'r') as f: data = json.load(f) before = len(data['patterns']) data['patterns'] = [p for p in data['patterns'] if p['id'] != '$MEMORY_ID'] after = len(data['patterns']) with open('$MEMORY_FILE', 'w') as f: json.dump(data, f, indent=2) if before > after: print(f'Forgotten: $MEMORY_ID') else: print(f'Not found: $MEMORY_ID') " ``` ### Technical Analysis Arguments controlled by the caller are inserted directly into source code supplied to `python3 -c`. The affected values include: - `$ENTRY`, which conta ...[truncated 2109 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Eliminate interpolation of arguments into Python source. - Pass all caller-controlled values as positional arguments: ```bash python3 - "$MEMORY_FILE" "$QUERY" <<'PY' import json import sys memory_file = sys.argv[1] query = sys.argv[2].lower() with open(memory_file, "r", encoding="utf-8") as f: data = json.load(f) PY ``` - Pass structured entries through standard input and parse them with `json.load(sys.stdin)` instead of embedding JSON inside a Python string literal. - Parse `--limit` in Bash or Python as an integer and enforce a safe range, such as `1` through `100`. - Treat memory IDs as data, not source code. Optionally validate them against the expected identifier format, such as `^em_[0-9]+_[0-9]+$`. - Validate option arity before reading `$2`, and reject unknown options instead of silently ignoring them. - Add regression tests containing quotes, triple quotes, line breaks, semicolons, backslashes, and Python syntax in every argument. ]]>
