Back to skill

Security audit

CSV Data Processor

Security checks for vulnerabilities and agentic risk

Overview

This is a normal CSV toolkit, but its filter and SQL export features have unsafe implementations that deserve review before installation.

Install only if you will use it on trusted data and trusted filter expressions. Avoid letting web pages, documents, or untrusted users choose the --where expression, and review generated SQL before importing it into any database.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

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`.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/csv_convert.py:36
Finding
SQL Injection Through Unquoted Identifiers and Unsafe Value Serialization## Vulnerability Details **File Location**: `scripts/csv_convert.py`, lines 36-62 **Vulnerability Type**: Injection into generated SQL statements **Risk Level**: Medium ### Vulnerable Code ```python def csv_to_sql(csv_path, delimiter, encoding, has_header, table): with open(csv_path, 'r', encoding=encoding) as f: reader = csv.reader(f, delimiter=delimiter) rows = list(reader) if not rows: return "" if has_header: cols = rows[0] data = rows[1:] else: cols = [f"col{i}" for i in range(len(rows[0]))] data = rows lines = [f"-- Converted from {csv_path}", f"CREATE TABLE IF NOT EXISTS {table} ({', '.join(cols)});", ""] for row in data: vals = [] for v in row: if v == '' or v is None: vals.append('NULL') else: try: float(v) vals.append(v) except ValueError: vals.append(repr(v)) lines.append(f"INSERT INTO {table} ({', '.join(cols)}) VALUES ({', '.join(vals)});") return '\n'.join(lines) ``` ### Technical Analysis The SQL converter builds statements through direct string interpolation. Three attacker-influenced inputs are embedded without SQL-aware validation or escaping: - The `table` value originates from the `--table` command-line argument. - Column identifiers originate from the first row of the CSV file. - Data values are serialized with Python's `repr()`, which is not an SQL literal encoder. SQL identifiers have dialect-specific quoting requirements. Directly joining CSV headers into `CREATE TABLE` and `INSERT` statements allows delimiters, parentheses, comments, and statement terminators in a malicious header to alter the generated SQL structure. The `--table` argument presents the same problem. Python `repr()` also does not guarantee valid or sa ...[truncated 1762 chars]
Remediation
## Remediation Suggestions Replace ad hoc SQL construction with dialect-aware generation. 1. Define the supported target SQL dialect explicitly. 2. Validate table and column names against a conservative identifier policy, such as letters, digits, and underscores with a valid leading character. 3. Alternatively, quote identifiers using the exact rules of the selected database dialect, including escaping embedded quote characters. 4. Do not use Python `repr()` to serialize SQL values. 5. Prefer importing through a database API using parameterized statements rather than generating executable SQL text. 6. If SQL text must be generated, use a trusted dialect-aware library to encode literals. 7. Avoid treating a value as safely numeric solely because `float()` accepts it; parse it into a numeric type and serialize the normalized value. 8. Reject duplicate, empty, malformed, or excessively long column names. 9. Add tests with quotes, statement terminators, comments, parentheses, Unicode characters, backslashes, and control characters in table names, headers, and values. 10. Warn users that generated SQL must not be executed until its source data and identifiers are trusted.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

eval() call detected

High
Category
Dangerous Code Execution
Content
except ValueError:
                        pass
            try:
                if eval(args.where, {"__builtins__": {}}, env):
                    filtered.append(row)
            except Exception as e:
                print(f"Filter error: {e}")
Confidence
93% confidence
Finding
The script evaluates a user-supplied `--where` expression with Python `eval`, which is inherently dangerous for untrusted input. Although `__builtins__` is removed and only row values are exposed, `eval` still parses and executes arbitrary Python expressions and has a long history of sandbox bypasses and denial-of-service abuse; this makes the filter mechanism unsafe in a general-purpose agent skill context where inputs may be attacker-controlled.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This markdown file documents commands that create output files such as combined.csv, joined.csv, and clean.csv, but it does not include any user-facing warning about potential overwrites or changes to user data. For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that could affect user data or system integrity.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/csv_filter.py:43