Back to skill

Security audit

CSV Tool Pro

Security checks for vulnerabilities and agentic risk

Overview

This CSV utility appears purpose-aligned, but it can silently overwrite user data and has unsafe handling of untrusted CSV content.

Install only if you are comfortable with a local CSV utility that can write files. Use explicit output paths, avoid running sort without --output on important data, keep backups, and be cautious when viewing or converting CSV files from untrusted sources.

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

Warning
Location
scripts/csv_tool.py:163
Finding
YAML Structure Injection Through Unescaped CSV Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/csv_tool.py`, lines 163–175 **Vulnerability Type**: Untrusted data injection into generated YAML **Risk Level**: Medium ### Vulnerable Code ```python def cmd_to_yaml(args): headers, rows, _ = read_csv(args.file) lines = [] for row in rows: lines.append('-') for i, h in enumerate(headers): val = row[i] if i < len(row) else '' lines.append(f' {h}: "{val}"') out = args.output or args.file.rsplit('.', 1)[0] + '.yaml' with open(out, 'w', encoding='utf-8') as f: f.write('\n'.join(lines) + '\n') print(f"Converted {len(rows)} rows → {out}") ``` ### Technical Analysis The YAML converter constructs output through direct string interpolation rather than a context-aware YAML serializer. Both the CSV header `h` and cell value `val` are attacker-controlled and are inserted without escaping quotation marks, backslashes, line breaks, document separators, or other YAML syntax. Although values are surrounded by double quotes, an embedded quote followed by a newline can terminate the intended scalar and introduce additional mappings or YAML documents. Headers are even less constrained because they are emitted directly as mapping keys. The resulting file may therefore contain a YAML structure different from the one intended by the converter. This is a data-to-configuration injection issue classified as `T09: Insecure Skill Coding Practices`. ### Attack Path 1. An attacker prepares a CSV file containing a malicious header or cell value with YAML metacharacters, quotation marks, and embedded line breaks. 2. A user invokes the `to-yaml` command on that CSV file. 3. `cmd_to_yaml` interpolates the malicious content directly into the output document. 4. The generated YAML contains attacker-created keys, values, or document boundaries. 5. If the generated file is subsequently used as application configuration or consumed by an automated process, ...[truncated 657 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use a maintained YAML serializer with safe dumping instead of constructing YAML through string concatenation. - Serialize both keys and values through the serializer so quotes, control characters, line breaks, and YAML metacharacters are encoded correctly. - If adding a dependency is not acceptable, implement and test strict scalar encoding for YAML keys and values. JSON-compatible quoting may be used for scalar values only after verifying that the resulting syntax is valid YAML. - Reject unexpected control characters and normalize line endings before serialization. - Parse the generated document with a safe YAML parser during tests and verify that its structure exactly matches the source rows. - Add regression tests covering embedded quotes, backslashes, multiline cells, colons, comment markers, document separators, and crafted headers. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/csv_tool.py:52
Finding
Terminal Control-Sequence Injection Through Untrusted CSV Fields<![CDATA[ ## Vulnerability Details **File Location**: `scripts/csv_tool.py`, lines 52–69, 203–219, and 224–259 **Vulnerability Type**: ANSI/ECMA-48 terminal control-sequence injection **Risk Level**: Medium ### Vulnerable Code ```python def cmd_view(args): headers, rows, _ = read_csv(args.file) n = args.rows or len(rows) rows = rows[:n] # Calculate column widths cols = [str(h) for h in headers] widths = [len(c) for c in cols] for row in rows: for i, cell in enumerate(row): if i < len(widths): widths[i] = max(widths[i], min(len(str(cell)), 50)) # Print table def fmt_row(cells): parts = [] for i, c in enumerate(cells): s = str(c)[:50] if i < len(widths) else str(c)[:50] parts.append(s.ljust(widths[i] if i < len(widths) else 10)) return ' | '.join(parts) sep = '-+-'.join('-' * w for w in widths) print(fmt_row(headers)) print(sep) for row in rows: print(fmt_row(row)) ``` Additional affected output paths include: ```python def cmd_frequency(args): headers, rows, _ = read_csv(args.file) col_idx = None for i, h in enumerate(headers): if h.lower() == args.column.lower(): col_idx = i break if col_idx is None: print(f"Column '{args.column}' not found") return counter = Counter(row[col_idx] for row in rows if col_idx < len(row)) print(f"\n📊 Frequency: {args.column}") for val, cnt in counter.most_common(20): pct = cnt / len(rows) * 100 bar = '█' * int(pct / 2) print(f" {str(val)[:30]:30s} {cnt:6d} ({pct:5.1f}%) {bar}") ``` ```python def cmd_pivot(args): headers, rows, _ = read_csv(args.file) row_col = row_val = col_col = col_val = val_col = None for i, h in enumerate(headers): hl = h.lower() if hl == args.row_column.lower(): row_col = i if hl == args.col_column.lower(): col_col = i ...[truncated 3188 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Sanitize every untrusted header and cell before writing it to an interactive terminal. - Remove or visibly encode the escape character, C0 controls, C1 controls, carriage returns, backspaces, and other non-printing characters. Preserve only intended formatting characters such as a normalized newline where explicitly required. - Consider rendering unsafe bytes using escaped notation such as `\x1b`, `\r`, and `\b` so users can inspect the original content safely. - Apply one centralized terminal-sanitization function to `view`, `frequency`, and `pivot`, including all headers, row keys, column keys, and values. - Detect whether standard output is a terminal with `sys.stdout.isatty()`. Terminal detection should supplement sanitization, not replace it, because output can later be replayed in a terminal. - Add tests containing CSI, OSC, carriage-return, backspace, and multiline payloads and verify that no raw control sequence reaches standard output. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (4)

Vague Triggers

Medium
Confidence
91% confidence
Finding
The manifest description has a broad activation trigger for general CSV, data cleaning, conversion, merge, dedupe, and statistics requests, which can cause the skill to activate in many loosely related file-handling situations. In a skill that can read and write files, overbroad routing increases the chance of unintended invocation and file modification outside the user's specific intent.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill advertises mutating operations such as merge, convert, and dedupe that save or alter files, but it does not warn about overwriting existing files or modifying data. This is dangerous because a broadly triggered file-processing skill may destroy or replace user data if output filenames collide or if users do not realize an operation is destructive.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The sort operation writes to `args.output or args.file`, which means running the command without `--output` will modify the original file in place. Although the status print occurs after the write, there is no prior warning or confirmation about this destructive behavior.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The manifest description embeds Chinese trigger guidance ('当用户需要处理CSV文件...时触发') alongside English content, which introduces an implicit language-specific behavior without explaining whether the skill is bilingual or locale-scoped. There is no explicit user opt-in or documented justification for the mixed-language activation policy.

Static analysis

No suspicious patterns detected.