Back to skill

Security audit

Automate Excel

Security checks for vulnerabilities and agentic risk

Overview

This Excel automation skill is mostly coherent, but it can overwrite workbooks and can carry unsafe formula-like data into generated Excel files.

Review before installing if you will process untrusted CSV, Excel, or template data. Use explicit output paths, keep backups before formatting or renaming workbooks, avoid opening generated files from untrusted inputs unless formula-like values are escaped, and consider pinning dependencies before use in sensitive environments.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/csv_to_excel.py:36
Finding
CSV Formula Injection in Generated Excel Workbooks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/csv_to_excel.py`, lines 36-44 and 55-60 **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python if args.input: path = Path(args.input) if not path.exists(): print(f"File does not exist: {path}", file=sys.stderr) sys.exit(1) df = pd.read_csv(path, encoding=args.encoding, sep=args.sep) sheet_name = args.sheet_name or path.stem if len(sheet_name) > 31: sheet_name = sheet_name[:31] df.to_excel(out, sheet_name=sheet_name, index=False, engine="openpyxl") ``` ```python with pd.ExcelWriter(out, engine="openpyxl") as writer: for path in paths: df = pd.read_csv(path, encoding=args.encoding, sep=args.sep) name = path.stem if len(name) > 31: name = name[:31] df.to_excel(writer, sheet_name=name, index=False) ``` ### Technical Analysis The script imports CSV values and writes them directly into an Excel workbook without distinguishing untrusted text from spreadsheet formulas. Values beginning with formula-significant characters such as `=`, `+`, `-`, or `@` may be interpreted as formulas when the resulting workbook is opened in Excel or another compatible spreadsheet application. An attacker who controls any CSV field can therefore place a formula payload in the generated workbook. Depending on the spreadsheet client and its security configuration, such a formula could create deceptive hyperlinks, access external resources, disclose workbook data through supported functions, or abuse legacy formula features. ### Attack Path 1. An attacker creates or modifies a CSV file processed by the Skill. 2. The attacker inserts a value such as: ```text =HYPERLINK("https://attacker.example/login","Open report") ``` 3. A user runs `csv_to_excel.py` against the attacker-controlled CSV. 4. The value is written to the output workbook without neutralization. 5. The use ...[truncated 652 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Treat imported CSV fields as untrusted text before exporting them to a workbook. 1. Detect strings whose first non-whitespace character is `=`, `+`, `-`, or `@`. 2. Prefix such strings with an apostrophe or explicitly set the target Excel cell type and number format to text. 3. Apply the mitigation to column names as well as data values. 4. Provide an explicit opt-in option for users who intentionally need formulas preserved. 5. Add regression tests covering all formula prefixes, leading whitespace, tab characters, and multi-file conversion. For example: ```python FORMULA_PREFIXES = ("=", "+", "-", "@") def neutralize_formula(value): if isinstance(value, str) and value.lstrip().startswith(FORMULA_PREFIXES): return "'" + value return value df = df.map(neutralize_formula) df.columns = [neutralize_formula(str(col)) for col in df.columns] ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/template_fill.py:17
Finding
Formula Injection Through Template Placeholder Substitution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/template_fill.py`, lines 17-27 and 70-75 **Vulnerability Type**: Spreadsheet formula injection through untrusted template data **Risk Level**: Medium ### Vulnerable Code ```python def _replace_placeholders(text, row_dict): if text is None or not isinstance(text, str): return text result = text for col, val in row_dict.items(): placeholder = "{{" + str(col) + "}}" if placeholder in result: result = result.replace( placeholder, str(val) if pd.notna(val) else "" ) result = re.sub(r"\{\{[^}]+\}\}", "", result) return result ``` ```python for col_idx in range(1, max_col + 1): src = ws.cell(row=pattern_row_idx, column=col_idx) cell = ws.cell(row=target_row, column=col_idx) cell.value = _replace_placeholders(src.value, row_dict) ``` ### Technical Analysis Values loaded from the data file are substituted directly into template cells. If a template cell consists solely of a placeholder and the corresponding untrusted value begins with `=`, the resulting `cell.value` begins with `=`. Openpyxl can consequently store that cell as a formula rather than literal text. The same issue may arise with other formula-significant prefixes depending on how the resulting workbook is interpreted by the spreadsheet application. No trust boundary, formula-preservation policy, or escaping mechanism is implemented. ### Attack Path 1. An attacker controls a row in the CSV or Excel data source used for template filling. 2. The template contains a cell such as `{{Website}}`. 3. The attacker supplies a value such as: ```text =HYPERLINK("https://attacker.example","View details") ``` 4. `template_fill.py` replaces the placeholder with the attacker-controlled value. 5. The resulting string is assigned directly to `cell.value`. 6. The user opens the generated workbook and the spreadsheet client treats the ce ...[truncated 509 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape untrusted substituted values when they would make the final cell begin with a formula-significant character. 2. Distinguish trusted template-authored formulas from untrusted data values. 3. When a cell contains only a placeholder, explicitly store untrusted output as text. 4. Consider a secure default that rejects formula-like values and an explicit option to permit trusted formula insertion. 5. Add tests for CSV and Excel data sources, placeholder-only cells, embedded placeholders, leading whitespace, and all relevant formula prefixes. A safe substitution layer could use logic such as: ```python FORMULA_PREFIXES = ("=", "+", "-", "@") def as_safe_spreadsheet_text(value): text = str(value) if text.lstrip().startswith(FORMULA_PREFIXES): return "'" + text return text ``` This function should be applied to every untrusted replacement before it is assigned to `cell.value`. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unbounded and Unhashed Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt`, lines 1-3; `scripts/requirements.txt`, lines 1-3 **Vulnerability Type**: Non-reproducible dependency resolution and supply-chain exposure **Risk Level**: Low ### Vulnerable Code ```text openpyxl>=3.1.0 pandas>=2.0.0 xlrd>=2.0.0 ``` The Skill documentation instructs users to install these dependencies with: ```bash pip install -r scripts/requirements.txt ``` ### Technical Analysis The requirements specify only minimum versions and do not establish upper bounds, exact reviewed versions, or package hashes. Every installation can therefore resolve to different future releases. The listed dependencies are established packages, and the audit found no malicious package name or unsafe package index. Nevertheless, mutable dependency resolution reduces build reproducibility and exposes users to future compromised, malicious, or incompatible releases that satisfy the minimum-version constraints. ### Attack Path 1. A user follows the documented installation command. 2. Pip resolves the newest releases satisfying the `>=` constraints. 3. A future upstream release is compromised or introduces unsafe behavior. 4. That release is installed without a lock file or hash-based integrity check. 5. Package code executes during import or when the spreadsheet scripts invoke the affected library. This path is conditional on an upstream compromise or unsafe future release; no currently malicious dependency was identified during the audit. ### Impact Assessment A compromised dependency would execute with the privileges of the user running the Skill and could potentially access files, environment data, and network resources available to that process. The current project does not request elevated privileges, so the exposure is limited to the invoking user's permissions. The immediate confirmed impact is non-reproducible installation behavior and reduced dependency integrity assurance. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin dependencies to exact, reviewed versions using `==`. 2. Generate a lock file with cryptographic hashes, for example with `pip-tools`. 3. Install with hash verification: ```bash pip install --require-hashes -r requirements.txt ``` 4. Keep the root and `scripts/requirements.txt` files synchronized or replace them with one canonical dependency specification. 5. Use automated dependency scanning and controlled update reviews. 6. Test every dependency update before changing the lock file. 7. Consider upper bounds where exact pins cannot be used. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (31)

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill description is broad enough to activate on many ordinary spreadsheet-related requests, which can cause the agent to invoke file-processing capabilities in situations where they were not clearly needed. Over-broad activation increases the chance of unnecessary access to local files and unintended data modification workflows, especially because this skill includes read/write and merge operations.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The invocation guidance says to apply the skill whenever the user needs Excel processing, batch conversion, or report generation, but it does not define boundaries or prerequisites for safe use. This ambiguity can lead the agent to select the skill without confirming file paths, write targets, or whether the user actually wants filesystem changes, increasing the risk of unintended operations.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill provides write and append examples, including saving back to an existing workbook, without an upfront warning about destructive changes or overwrite risk. In an agent context, this omission is dangerous because it normalizes in-place modification and may cause loss of original data, corruption of reports, or accidental alteration of sensitive spreadsheets.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file’s instructional content, headings, and example descriptions are entirely in Chinese, which effectively forces a specific language for users. The policy allows locale or language constraints only when the skill offers user choice or clearly documents and justifies the restriction.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This markdown file documents `rename_sheets.py`, `format_conditional.py`, and `format_columns_as_text.py` as having optional `--output` parameters with default overwrite behavior, but it does not warn users that omitting `--output` will modify the original workbook in place. Because this behavior can affect user data integrity, the skill description should explicitly disclose it.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
df_main.to_csv("sample.csv", index=False, encoding="utf-8-sig")

# 模板:第一行表头,第二行占位符 {{姓名}} {{金额}}
wb_tpl = __import__("openpyxl").Workbook()
ws = wb_tpl.active
ws["A1"], ws["B1"], ws["C1"] = "姓名", "金额", "地区"
ws["A2"], ws["B2"], ws["C2"] = "{{姓名}}", "{{金额}}", "{{地区}}"
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The module docstring is entirely in Chinese, and the CLI description/help text is likewise Chinese-only, which imposes a specific language on users. The policy allows locale constraints only when they are optional or clearly justified, neither of which is present here.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This code file contains natural-language usage instructions exclusively in Chinese, and later error/output strings are also Chinese-only. The policy prohibits forcing a specific language or locale unless the skill offers a language choice or clearly documents a justified regional constraint, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The module docstring and command help examples are written entirely in Chinese, and the user-facing argparse descriptions and runtime messages are also Chinese-only. This imposes a specific language on users without opt-in or an explanation that the skill is intentionally region-specific, which matches the locale-policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring, CLI argument help text, and runtime messages are all written in Chinese, which imposes a specific language on users. The file does not offer localization, a language switch, or any indication that the skill is intentionally limited to a Chinese-speaking context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstring is entirely in Chinese, and the command description is presented only in that language. This creates a language policy concern because the skill imposes a specific locale on users without any opt-in, alternative language support, or stated region-specific justification.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
Multiple stderr/stdout messages such as skipped-path notices, failure messages, and the final success message are emitted only in Chinese. Forcing a single language in user-facing strings without opt-in or documented justification violates the natural-language policy criteria.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The docstring and command-line help text are entirely in Chinese, which imposes a specific language/locale on users of the skill. The file does not offer an alternative language choice or explain that the skill is intentionally limited to a Chinese-speaking context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The docstring and CLI help text are written entirely in Chinese, including the script description and usage guidance. Under the policy rule, forcing a specific language without user opt-in or a documented justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstring and CLI help text are entirely in Chinese, which imposes a specific language on all users. Under the policy, locale/language restrictions should either be optional or clearly justified as region-specific; neither is present here.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstring, CLI argument descriptions, and runtime status messages are all written only in Chinese. This imposes a specific language on users without any documented opt-in or alternative, which matches the locale/language policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file's docstring, argument descriptions, and user-facing output are written only in Chinese, which imposes a specific language on users. The policy allows locale constraints only when users are given a choice or the restriction is clearly documented and justified, neither of which appears here.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The skill heading and usage guidance are presented in Chinese, while there is no indication that the user can opt into another language. This can violate language/locale policy when a skill imposes a specific language without explicit user choice or documented regional justification.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This markdown file includes example commands and code that create or save output files such as `data/merged.xlsx`, but it does not warn users that running these examples will write new files and may overwrite existing outputs. Under the markdown-specific missing-warning criterion, behaviors affecting user data or files should be disclosed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
openpyxl>=3.1.0
pandas>=2.0.0
xlrd>=2.0.0
Confidence
95% confidence
Finding
The dependency is specified with only a lower bound, so builds may resolve to different versions over time. This weakens supply-chain reproducibility and can unexpectedly introduce vulnerable or breaking releases into an automation skill that processes untrusted spreadsheet files.

Unverifiable Dependency: openpyxl has 2 known advisory(ies) (CVE-2017-5992 (Improper Restriction of XML External Entity Reference in Openpyxl); CVE-2017-5992 (Openpyxl 2.4.1 resolves external entities by default, which allows remote attack)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding
The manifest does not pin openpyxl, and openpyxl has historical advisories related to XML external entity handling. Because this skill parses spreadsheet content, an affected resolved version could expose the environment to malicious workbook input, making the lack of version certainty a real security concern.

Unpinned Dependencies

Low
Category
Supply Chain
Content
openpyxl>=3.1.0
pandas>=2.0.0
xlrd>=2.0.0
Confidence
95% confidence
Finding
Using an unpinned pandas version allows dependency drift, making installs non-reproducible and increasing the chance that a newly released vulnerable or incompatible version is pulled in. In a file-processing skill, this can affect integrity and security of data-handling behavior.

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
openpyxl>=3.1.0
pandas>=2.0.0
xlrd>=2.0.0
Confidence
94% confidence
Finding
An unpinned xlrd dependency permits uncontrolled version selection at install time, which is a supply-chain hygiene weakness. Although low severity on its own, it reduces assurance that deployments consistently use a reviewed package version.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
This code file contains natural-language strings for the docstring and argument help text exclusively in Chinese. Under the stated policy, forcing a specific language without offering a choice or documenting a justified locale constraint is a natural-language policy violation.

Static analysis

No suspicious patterns detected.