T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/chart_generator.py:111
- Finding
- Unsandboxed Execution of Generated Python Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/chart_generator.py:111-133` **Vulnerability Type**: Arbitrary code execution through untrusted generated code **Risk Level**: High ### Vulnerable Code ```python def execute_chart_code(code: str) -> tuple: """ Execute generated Matplotlib code and return (success, output_path, error). """ import os, sys, tempfile try: output_dir = os.path.join(os.path.expanduser("~"), ".qclaw", "workspace", "outputs") os.makedirs(output_dir, exist_ok=True) # Write the code to a temporary file and execute it code_path = os.path.join(output_dir, "_temp_chart.py") with open(code_path, "w", encoding="utf-8") as f: f.write(code) import subprocess result = subprocess.run( ["python", code_path], capture_output=True, text=True, timeout=60, cwd=output_dir ) ``` ### Technical Analysis The `execute_chart_code` function accepts a Python source string, writes it to a predictable local file, and executes it using the system Python interpreter. There is no validation of the source code, AST inspection, import allowlist, operating-system sandbox, privilege restriction, network isolation, or user confirmation. The surrounding chart-generation module builds prompts asking an LLM to produce executable Python. If attacker-controlled paper content influences the generated response, or if the LLM/API is compromised, the returned chart code can contain arbitrary Python operations instead of only Matplotlib drawing instructions. Using `shell=False` does not mitigate this issue because the attacker controls the contents of the Python file rather than the subprocess command-line arguments. The executed program receives the same filesystem access, environment variables, network access, and operating-system identity as the Agent process. The fixed `_temp_chart.py` filename also cr ...[truncated 1595 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Do not execute LLM-generated source code.** Require the model to return a strict data structure containing chart type, labels, series, values, colors, and captions. Validate it against a schema and render it using fixed, trusted Matplotlib functions. 2. If generated code execution cannot be removed, run it in a disposable, hardened container or micro-VM with: - No Agent secrets or inherited environment variables. - No network access. - A read-only root filesystem. - A dedicated writable output directory. - A nonprivileged UID and GID. - Linux namespace, seccomp, and capability restrictions. - Strict CPU, memory, process, file-size, and execution-time limits. 3. Parse the code with Python's `ast` module and reject imports, attribute access, subprocesses, file access, dynamic evaluation, networking, reflection, and other operations outside a narrowly defined allowlist. AST validation should supplement, not replace, operating-system isolation. 4. Require explicit user approval before running generated code and display the exact source that will execute. 5. Use a securely created unique temporary file or directory rather than the predictable `_temp_chart.py` path, and guarantee cleanup with a `finally` block. 6. Invoke the intended interpreter through `sys.executable` rather than relying on a potentially different `python` executable from `PATH`. ]]>
