Back to skill

Security audit

Review Summary

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local Excel report generator that fits its stated purpose, with a caution to use trusted input spreadsheets because formulas may carry into the generated workbook.

Install only if you need this Chinese budget-review Excel workflow. Use source spreadsheets from trusted project systems, review generated workbooks before sharing, and be cautious opening outputs made from third-party or attacker-supplied Excel files because embedded formulas in input text may remain active in the output.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_review_summary.py:302
Finding

Spreadsheet Formula Injection Through Untrusted Excel Input

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_review_summary.py, lines 302-359
Vulnerability Type: Spreadsheet formula injection
Risk Level: Medium

Vulnerable Code

The data-reference worksheet directly writes text obtained from source workbooks:

python
for seq, item in enumerate(items, 1):
    cell(ws, r, 1); cell(ws, r, 2, seq)
    ws.cell(row=r, column=3, value=item['unit_eng'])
    ws.cell(row=r, column=4, value=item['code'])
    ws.cell(row=r, column=5, value=item['name'])
    ws.cell(row=r, column=6, value=item['desc'][:500] if item['desc'] else '')
    ws.cell(row=r, column=7, value=item['unit'])
    for c2, k in [(8, 'send_qty'), (9, 'send_price'), (10, 'send_total'),
                   (11, 'review_qty'), (12, 'review_price'), (13, 'review_total'), (14, 'diff')]:
        cell(ws, r, c2, item[k], fmt=NUM_FMT)
    ws.cell(row=r, column=15, value=item['reason'][:500] if item['reason'] else item['analysis'])
    ws.cell(row=r, column=16, value=item['cat_name'])
    ws.cell(row=r, column=18, value='电力工程')
    r += 1

The detailed worksheet writes the same untrusted fields without neutralization:

python
for idx, item in enumerate(cat_items):
    ws.cell(row=r, column=1, value=f"{cat_id}.{idx + 1}")
    ws.cell(row=r, column=2, value=item['unit_eng'])
    ws.cell(row=r, column=3, value=item['code'])
    ws.cell(row=r, column=4, value=item['name'])
    ws.cell(row=r, column=5, value=item['desc'][:500] if item['desc'] else '')
    ws.cell(row=r, column=6, value=item['unit'])
    for c2, k in [(7, 'send_qty'), (8, 'send_price'), (9, 'send_total'),
                   (10, 'review_qty'), (11, 'review_price'), (12, 'review_total'), (13, 'diff')]:
        cell(ws, r, c2, item[k], fmt=NUM_FMT)
    ws.cell(row=r, column=14, value=item['reason'][:500] if item['reason'] else item['analysis'])
    ws.cell(row=r, column=15, value=item['cat_name'])
    r += 1

Technical Analysis

Text fields imported from the ...[truncated 2707 chars]

Remediation
View remediation

Remediation Suggestions

Introduce a centralized function for all text written to spreadsheet cells. At minimum, values beginning with = must be converted to literal text. For defense in depth and compatibility with different spreadsheet clients and export formats, also neutralize leading +, -, and @ characters after accounting for leading whitespace, tabs, carriage returns, and line feeds.

python
FORMULA_PREFIXES = ('=', '+', '-', '@')

def safe_excel_text(value):
    if value is None:
        return ''

    text = str(value)
    normalized = text.lstrip(' \t\r\n')

    if normalized.startswith(FORMULA_PREFIXES):
        return "'" + text

    return text

Apply this function to every externally sourced textual value before assigning it to a cell:

python
ws.cell(row=r, column=3, value=safe_excel_text(item['unit_eng']))
ws.cell(row=r, column=4, value=safe_excel_text(item['code']))
ws.cell(row=r, column=5, value=safe_excel_text(item['name']))
ws.cell(row=r, column=6, value=safe_excel_text(item['desc'][:500]))
ws.cell(row=r, column=15, value=safe_excel_text(
    item['reason'][:500] if item['reason'] else item['analysis']
))

Apply equivalent protection to all other imported text and to user-controlled command-line values such as project names, company names, and notes. Numeric fields should continue to be validated and written as numeric types rather than passed through the text sanitizer.

Add regression tests that generate workbooks from values beginning with =, +, -, @, whitespace followed by a formula prefix, tabs, and line breaks. Reload the output with openpyxl and verify that protected cells are stored as literal strings rather than formulas. Where feasible, also test the generated workbook in the spreadsheet clients used by reviewers.

Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstring and generated workbook/output labels are written in Chinese, and the script is positioned as generating a fixed-format Chinese review summary. This appears to impose a specific language/locale behavior without any documented opt-in or alternative language selection, which matches the language/locale policy concern for natural-language content.

Content

No source excerpt is available for this finding.