T09 · Insecure Skill Coding Practices
Error
- Location
- setup.sh:165
- Finding
- Python Code Injection Through Unsafely Interpolated Setup Inputs<![CDATA[ ## Vulnerability Details **File Location**: `setup.sh`, lines 165-178 and 190-200 **Vulnerability Type**: Unsanitized data embedded in executable Python source **Risk Level**: High ### Vulnerable Code ```bash # Save to ~/.x-scout/config.json python3 -c " import json config = { 'install_id': '$INSTALL_ID', 'twitterapi_key': '$TW_KEY', 'openrouter_key': '${OR_KEY:-}', 'cerebras_keys': '${CB_KEYS:-}', 'deepgram_key': '${DG_KEY:-}', } with open('$XS_CONFIG', 'w') as f: json.dump(config, f, indent=2) " ``` A second vulnerable interpolation occurs when constructing the registration payload: ```bash REGISTER_PAYLOAD=$(python3 -c " import json, platform print(json.dumps({ 'tool': 'x-scout', 'install_id': '$INSTALL_ID', 'email': '${USER_EMAIL:-}', 'platform': platform.system(), 'python': '$PY_VER', 'has_openrouter': bool('${OR_KEY:-}'), 'has_cerebras': bool('${CB_KEYS:-}'), 'has_deepgram': bool('${DG_KEY:-}'), })) ") ``` ### Technical Analysis Values collected from interactive prompts or inherited environment variables are inserted directly into source code passed to `python3 -c`. These values are treated as part of the Python program rather than as data. An attacker-controlled value containing a quote and valid Python statements can terminate the intended string literal and inject additional Python expressions. No escaping or syntactic validation is applied before interpolation. For example, a crafted key following this general structure can alter the generated Python program: ```text '; __import__("os").system("ATTACKER_COMMAND"); injected=' ``` The vulnerable inputs include the TwitterAPI.io, OpenRouter, Cerebras, and Deepgram keys, as well as the optional registration email. Environment-provided values are affected in addition to interactively entered values. ### Attack Path 1. An attacker persuades a user to run `setup.sh` with a malicious API-key environment variable, supplies a crafted v ...[truncated 1004 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Never insert external values into Python source code. - Pass values through environment variables, standard input, or positional arguments and read them as data inside Python. - A safe environment-based pattern is: ```bash export INSTALL_ID TW_KEY OR_KEY CB_KEYS DG_KEY XS_CONFIG python3 <<'PY' import json import os config = { "install_id": os.environ["INSTALL_ID"], "twitterapi_key": os.environ["TW_KEY"], "openrouter_key": os.environ.get("OR_KEY", ""), "cerebras_keys": os.environ.get("CB_KEYS", ""), "deepgram_key": os.environ.get("DG_KEY", ""), } with open(os.environ["XS_CONFIG"], "w", encoding="utf-8") as output: json.dump(config, output, indent=2) PY ``` - Construct the registration payload with the same data-only pattern. - Do not rely on ad hoc quote escaping; environment variables or structured standard input avoid source-code generation entirely. - Add regression tests using values containing single quotes, double quotes, newlines, semicolons, and Python syntax. ]]>
