Back to skill

Security audit

work-estimation-zh

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated purpose, but its Excel generator can carry unsafe formulas from requirement text into generated spreadsheets.

Review before installing if generated spreadsheets may be opened by others or built from untrusted requirement text. Ask the publisher to escape formula-like cell values, confirm before reading local requirement files, and disclose the exact output path before writing reports.

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_estimation.py:78
Finding
Spreadsheet Formula Injection Through Untrusted Requirement Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_estimation.py:78-85`, with untrusted values reaching the sink at `scripts/generate_estimation.py:185-186`, `scripts/generate_estimation.py:274-278`, and `scripts/generate_estimation.py:550-554` **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python def set_cell(ws, row, col, value, bold=False, align='left', fill=None): cell = ws.cell(row=row, column=col, value=value) cell.font = Font(bold=bold) cell.alignment = Alignment(horizontal=align, vertical='center') cell.border = BORDER_THIN if fill: cell.fill = fill return cell ``` Examples of requirement-derived values reaching this sink without sanitization include: ```python set_cell(ws, row, 1, module["name"]) set_cell(ws, row, 2, item["name"]) ``` ```python set_cell(ws, row, 1, module["name"]) set_cell(ws, row, 2, item["name"]) set_cell(ws, row, 3, item.get("desc", "")) set_cell(ws, row, 4, hours, align='center') set_cell(ws, row, 5, item.get("basis", f"Based on {sheet_name} standard")) ``` ```python set_cell(ws, row, 1, module["name"]) set_cell(ws, row, 2, item["name"]) set_cell(ws, row, 3, item.get("prerequisite", "-")) set_cell(ws, row, 4, item.get("coordination", "-")) set_cell(ws, row, 5, item.get("coord_target", "To be confirmed")) ``` ### Technical Analysis The Skill accepts user-supplied requirement descriptions or requirement documents and converts their content into module names, item names, descriptions, prerequisites, coordination details, and other workbook fields. The generic `set_cell()` function passes these strings directly to `openpyxl` without distinguishing plain text from formulas. A string beginning with `=` can be stored as an Excel formula. Depending on the spreadsheet application and its compatibility rules, values beginning with `+`, `-`, or `@` may also be interpreted as formulas. Leading whitespace, tabs, or control characte ...[truncated 2387 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Centralize spreadsheet-safe text handling in `set_cell()` so every workbook sheet receives consistent protection. 2. Treat all user-controlled or AI-derived descriptive fields as text rather than formulas. 3. Normalize leading control characters and inspect the first meaningful character for formula prefixes such as `=`, `+`, `-`, and `@`. 4. Prefix unsafe values with an apostrophe or otherwise encode them as literal text before assigning them to the cell. 5. Preserve numeric types only for fields that have passed strict numeric validation. 6. Add explicit length and character restrictions for names, descriptions, prerequisites, risk details, and coordination fields. 7. Add tests covering direct formula prefixes and bypass variants involving spaces, tabs, carriage returns, and line feeds. 8. Document that requirement documents are untrusted inputs and that generated workbooks must not contain executable formulas from those inputs. A centralized hardening pattern could be implemented as follows: ```python FORMULA_PREFIXES = ("=", "+", "-", "@") def spreadsheet_safe_value(value): if not isinstance(value, str): return value normalized = value.lstrip("\t\r\n") if normalized.startswith(FORMULA_PREFIXES): return "'" + value return value def set_cell(ws, row, col, value, bold=False, align="left", fill=None): safe_value = spreadsheet_safe_value(value) cell = ws.cell(row=row, column=col, value=safe_value) cell.font = Font(bold=bold) cell.alignment = Alignment(horizontal=align, vertical="center") cell.border = BORDER_THIN if fill: cell.fill = fill return cell ``` Where practical, use an allowlist for fields expected to contain only identifiers or short names. Security tests should then open the generated workbook with `openpyxl` using `data_only=False` and verify that attacker-controlled cells have `data_type == "s"` rather than formula type `f`. ]]>
Vulnerability Patterns
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • 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
Findings (8)

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
All user-facing documentation and example invocations in this file are written in Chinese, effectively imposing a single language on users without offering an explicit language or locale choice. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The README uses broad natural-language trigger phrases around common project-estimation requests, which increases the chance the skill activates on ordinary conversation without clear user intent to run this specific capability. In this skill’s context, unintended activation could lead to unnecessary processing of requirement text or local files and generation of output artifacts, making the trigger design meaningfully risky rather than purely cosmetic.

Vague Triggers

Medium
Confidence
97% confidence
Finding
The trigger phrase includes the broad term “项目评估”, which can match many ordinary conversations unrelated to software effort estimation. This can cause the skill to activate unexpectedly, leading to unintended handling of user content or workflow confusion, though the skill itself does not contain obviously harmful behavior.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file consistently defines evaluation names, requirement text, and expected dimension labels only in Chinese, which signals a locale-specific constraint in the skill's natural-language behavior. There is no indication that users can choose another language or that the Chinese-only requirement is explicitly justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The module docstring and user-facing outputs are written entirely in Chinese, indicating the skill is designed around a single language/locale. The file does not offer any user choice or document a justified region-specific constraint, which can violate language/locale policy requirements.

Unbounded Output

Medium
Category
Output Handling
Content
def auto_width(ws):
    for column in ws.columns:
        max_length = 0
        column_letter = get_column_letter(column[0].column)
        for cell in column:
            try:
Confidence
75% confidence
Finding
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Missing User Warnings

Low
Confidence
93% confidence
Finding
The README advertises reading a local requirements document from a filesystem path and generating an Excel report, but provides no warning, consent step, or explanation of what files will be accessed and where outputs will be written. In an agent environment, this can normalize silent local file access and file creation, increasing the risk of surprising data exposure, misuse of sensitive documents, or unintended writes.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
SQP-3 applies to all file types and covers language or locale policy violations. This guide presents all instructions and content exclusively in Chinese, with no indication that the user can select another language or that the file is intentionally limited to a Chinese-speaking context.

Static analysis

No suspicious patterns detected.