Back to skill

Security audit

Pans Excel

Security checks for vulnerabilities and agentic risk

Overview

This Excel helper is mostly purpose-aligned, but its bundled script can evaluate spreadsheet data input as Python code, which makes it unsafe without review.

Install only if you trust the publisher and can restrict how commands are invoked. Do not pass untrusted --data values, avoid importing attacker-supplied CSV/JSON without formula sanitization, and be aware that formatting, charting, cleaning, validation, and autofmt commands may overwrite the workbook unless an output path is provided.

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/excel.py:1772
Finding
Arbitrary Python Code Execution Through Unsafe Data Parsing<![CDATA[ ## Vulnerability Details **File Location**: `scripts/excel.py:1772-1776` **Vulnerability Type**: Unsafe use of `eval()` on attacker-controlled command-line input **Risk Level**: High ### Complete Code Snippet ```python def ld(s): try: return json.loads(s) except: try: return eval(s) except: return {} ``` The active `main_v3()` command handlers subsequently pass the user-controlled `--data` argument to this function: ```python if args.cmd == "create": path = X().from_dict(ld(args.data), args.sheet).save(args.output) elif args.cmd == "report": d = ld(args.data) ``` The same unsafe parsing pattern also appears in the legacy command handler at `scripts/excel.py:887-891`. ### Technical Analysis The parser first attempts to decode the supplied value as JSON. If JSON parsing fails, it passes the original string directly to Python's `eval()` function. Unlike a data parser, `eval()` evaluates arbitrary Python expressions in the context of the running process. The `--data` parameter is directly controllable by anyone able to invoke or influence invocation of the Skill. The `create`, `report`, and `dashboard` commands in the active `main_v3()` implementation call `ld(args.data)` without validation or sandboxing. Consequently, a malformed JSON value containing a Python expression becomes a code-execution payload. Catching exceptions does not provide security because side effects can occur before the expression returns or raises an exception. ### Attack Path 1. An attacker influences the `--data` argument passed to `scripts/excel.py`. 2. The attacker supplies text that is not valid JSON but is a valid Python expression, for example: ```bash python3 scripts/excel.py create \ --data '__import__("os").system("id > /tmp/eval-proof")' \ --output out.xlsx ``` 3. `json.loads()` rejects the value. 4. Execution enters the fallback and evaluates the payload with `eval(s)`. 5. The operating-system command runs w ...[truncated 948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every `eval()` fallback, including the duplicate implementation at `scripts/excel.py:887-891`. 2. Require strict JSON and return a clear error when parsing fails: ```python def ld(value): try: data = json.loads(value) except json.JSONDecodeError as exc: raise ValueError(f"Invalid JSON data: {exc}") from exc if not isinstance(data, dict): raise ValueError("Input data must be a JSON object") return data ``` 3. Validate the resulting schema before processing it. Require string keys and expected value types, such as arrays of supported scalar values. 4. If support for Python literals is absolutely necessary, use `ast.literal_eval()` rather than `eval()`, followed by the same strict schema validation. Strict JSON is preferable. 5. Add tests proving that expressions involving `__import__`, function calls, attribute access, and comprehensions are rejected without side effects. 6. Place limits on input size, number of columns, and number of rows to reduce memory-exhaustion risks. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/excel.py:96
Finding
Spreadsheet Formula Injection During CSV and JSON Import<![CDATA[ ## Vulnerability Details **File Location**: `scripts/excel.py:96-114` **Vulnerability Type**: Spreadsheet formula injection caused by writing untrusted values directly into XLSX cells **Risk Level**: Medium ### Complete Code Snippet ```python def from_dict(self,data:Dict,sheet="数据")->'X': self.new(sheet) headers=list(data.keys()) nr=max((len(v) for v in data.values()),default=0) # 标题 self.ws.merge_cells(f"A1:{get_column_letter(len(headers))}1") c=self.ws["A1"]; c.value=f"📊 {sheet}"; ap(c,ST["title"]); c.fill=fill(C["gray_l"]) # 表头 for col,h in enumerate(headers,1): cell=self.ws.cell(row=3,column=col,value=h); ap(cell,ST["h"]) # 数据 for r in range(nr): bg=C["gray_l"] if r%2==0 else C["white"] for col,h in enumerate(headers,1): val=data[h][r] if r<len(data[h]) else "" cell=self.ws.cell(row=4+r,column=col,value=val) cell.fill=fill(bg); ap(cell,{"sz":10,"ha":"center"}) ``` The import handlers pass CSV and JSON values into this method without formula neutralization: ```python if ext == ".csv": d = IO.read_csv(args.file); out = args.output or args.file.replace(".csv",".xlsx") X().from_dict(d).save(out) elif ext == ".json": d = IO.read_json(args.file); out = args.output or args.file.replace(".json",".xlsx") X().from_dict(d).save(out) ``` ### Technical Analysis CSV and JSON field values are treated as trusted cell contents. A string beginning with `=` can be recognized by `openpyxl` and spreadsheet applications as a formula rather than inert text. The implementation does not distinguish trusted formulas from untrusted imported values. An attacker who controls an imported file can therefore place formulas in data fields. The generated XLSX document carries those formulas into Excel or another compatible spreadsheet application. Their behavior depends on the spreadsheet client and its security settings, but formulas may initiate external r ...[truncated 1744 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all imported CSV and JSON values as text unless an explicit trusted-formula mode is requested. 2. Neutralize strings that begin with formula-significant characters. At minimum, handle `=`; for defense in depth and compatibility across spreadsheet clients, also consider `+`, `-`, `@`, tabs, carriage returns, and leading whitespace before these markers. 3. Use a centralized sanitizer before assigning imported values: ```python def safe_spreadsheet_value(value): if not isinstance(value, str): return value probe = value.lstrip() if probe.startswith(("=", "+", "-", "@")): return "'" + value return value ``` 4. Assign sanitized values and explicitly format them as text where appropriate: ```python value = safe_spreadsheet_value(val) cell = self.ws.cell(row=4 + r, column=col, value=value) if isinstance(value, str) and value.startswith("'"): cell.number_format = "@" ``` 5. Keep formula creation behind a separate, explicit API that only accepts trusted formula templates. Do not infer formula permission from imported content. 6. Apply equivalent protection when exporting attacker-controlled data to CSV, because spreadsheet software may evaluate formula-like CSV fields when the exported file is opened. 7. Add regression tests using values such as `=1+1`, formulas containing external references, leading whitespace followed by `=`, and benign ordinary text. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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 (56)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This mismatch points to undisclosed risky behavior: parsing user data with eval() would permit code execution, and invoking LibreOffice via subprocess introduces shell/external program execution risk. Even though the code is not shown here, a skill description that hides code execution and external process invocation materially increases the danger because users and orchestrators cannot apply informed trust boundaries.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This mismatch points to undisclosed risky behavior: parsing user data with eval() would permit code execution, and invoking LibreOffice via subprocess introduces shell/external program execution risk. Even though the code is not shown here, a skill description that hides code execution and external process invocation materially increases the danger because users and orchestrators cannot apply informed trust boundaries.

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/excel.py create -d '{"部门":["华东","华南"],"销售额":[125,98],"利润":[31,20]}' -o out.xlsx
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/excel.py:890