T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/test-cli-commands.sh:143
- Finding
- Arbitrary Python Code Injection Through POOL_ID<![CDATA[ ## Vulnerability Details **File Location**: `scripts/test-cli-commands.sh`, lines 143-160 **Vulnerability Type**: Python source-code injection through unsafe string interpolation **Risk Level**: High ### Vulnerable Code ```bash test_pool_show() { local pool_id="${POOL_ID:-}" if [ -z "$pool_id" ]; then echo "=== TC-10: show-pool (SKIPPED - no POOL_ID) ===" return fi echo "=== TC-10: show-pool --pool-id $pool_id ===" if [ "$EXECUTOR" = "cli" ]; then cloudrobo resource show-pool --pool-id "$pool_id" 2>&1 | head -20 elif [ "$EXECUTOR" = "sdk" ]; then python3 -c " from cloudrobo_resource.client import ResourceClient from cloudrobo_core.sdk import Config, HttpClient client = ResourceClient(HttpClient(Config())) result = client.show_pool('$pool_id') print(str(result)[:500]) " 2>&1 | head -20 fi } ``` ### Technical Analysis The `POOL_ID` environment variable is interpolated directly into source code passed to `python3 -c`. Although the shell variable appears inside a Python single-quoted string, no escaping or UUID validation is applied. An attacker can include a single quote, Python statement separators, and arbitrary Python expressions in `POOL_ID`. The resulting text breaks out of the intended `client.show_pool()` argument and becomes executable Python code. Shell quoting around the outer multiline argument does not prevent this vulnerability because the shell deliberately expands `$pool_id` before passing the generated program to Python. ### Attack Path 1. An attacker controls or influences the `POOL_ID` environment variable, such as through an untrusted CI parameter. 2. The test suite is executed in SDK mode: ```bash bash scripts/test-cli-commands.sh -s . -e sdk ``` 3. The script expands the malicious value into the `python3 -c` program. 4. The injected value terminates the intended Python string and inserts additional Python statements. 5. Python executes those statements with ...[truncated 826 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Do not construct Python source code using an environment variable. Pass the pool ID as data through a positional argument: ```bash python3 - "$pool_id" <<'PY' import sys from cloudrobo_resource.client import ResourceClient from cloudrobo_core.sdk import Config, HttpClient pool_id = sys.argv[1] client = ResourceClient(HttpClient(Config())) result = client.show_pool(pool_id) print(str(result)[:500]) PY ``` Additionally: 1. Validate `POOL_ID` as a UUID before using it: ```bash if ! [[ "$pool_id" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ ]]; then echo "ERROR: POOL_ID must be a valid UUID." >&2 exit 1 fi ``` 2. Avoid embedding any externally controlled value in `python3 -c`, shell commands, or generated source code. 3. Add negative tests containing quotes, newlines, semicolons, and Python expressions to verify that input remains data rather than code. 4. Run tests with narrowly scoped credentials and an isolated, non-privileged runner. ]]>
