T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/csv_filter.py:29
- Finding
- Arbitrary Python Code Execution Through Unsafe Filter Evaluation## Vulnerability Details **File Location**: `scripts/csv_filter.py`, lines 29-47 **Vulnerability Type**: Unsafe evaluation of user-controlled expressions **Risk Level**: High ### Vulnerable Code ```python if args.where: filtered = [] for row in data: env = {k: v for k, v in row.items()} # Try numeric conversion for comparison for k, v in env.items(): try: env[k] = int(v) except ValueError: try: env[k] = float(v) except ValueError: pass try: if eval(args.where, {"__builtins__": {}}, env): filtered.append(row) except Exception as e: print(f"Filter error: {e}") sys.exit(1) data = filtered ``` ### Technical Analysis The value supplied through the `--where` command-line argument is passed directly to Python's `eval()`. Although the global namespace replaces `__builtins__` with an empty dictionary, this does not create a secure sandbox. Python expressions can traverse the object model through attributes such as class metadata, base classes, subclasses, and function global namespaces. Depending on classes already loaded in the interpreter, an attacker may recover access to built-in functions or other runtime capabilities. This can permit file access, module loading, or operating-system command execution. The documented interface encourages users or an AI Agent to place filter expressions directly in `--where`. Therefore, an attacker who influences that expression can cross the boundary from data filtering into arbitrary Python execution. ### Attack Path 1. An attacker supplies or recommends a crafted value for the `--where` argument. 2. A user or AI Agent invokes `csv_filter.py` with that expression. 3. The script passes the expression to `eval()` for every CSV row. 4. The express ...[truncated 926 chars]
- Remediation
- ## Remediation Suggestions Remove `eval()` entirely and implement an allowlisted expression parser. 1. Parse the expression with `ast.parse()` in expression mode or use a dedicated filtering grammar. 2. Permit only the required syntax, such as: - Boolean operations: `and`, `or`, and `not` - Comparisons: equality, inequality, and ordered comparisons - Column identifiers - String and numeric literals 3. Explicitly reject function calls, attribute access, subscripting, comprehensions, lambda expressions, imports, and all other AST node types. 4. Validate every identifier against the CSV column names. 5. Evaluate the validated syntax through custom comparison logic rather than compiling and executing it as Python. 6. Add tests containing object-traversal and function-call payloads to ensure they are rejected. 7. If a full expression language is unnecessary, replace `--where` with structured arguments such as `--column`, `--operator`, and `--value`.
