Back to skill

Security audit

Excel Data Import

Security checks for vulnerabilities and agentic risk

Overview

This spreadsheet import skill mostly matches its purpose, but it needs Review because it can mishandle sensitive spreadsheet data and some safety controls are weaker than documented.

Install only in a controlled workspace and use copies of spreadsheets. Treat generated workbooks, backups, logs, and reports as potentially sensitive. Do not rely on dry-run being side-effect free, do not rely on the documented encrypt/custom validation behavior unless fixed, and avoid importing untrusted spreadsheets until formula-like values are neutralized or rejected.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/excel_import.py:818
Finding
Untrusted spreadsheet values can be written as executable formulas<![CDATA[ ## Vulnerability Details **File Location**: `scripts/excel_import.py:818-829` **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: High ### Complete Code Snippet ```python for col, value in write_plan: target_cell = self.target_ws.cell(row=target_row, column=col) if is_cell_merged(target_cell, self.target_ws.merged_cells.ranges): continue cached_styles = { "number_format": target_cell.number_format, "font": copy.copy(target_cell.font) if target_cell.font else None, "fill": copy.copy(target_cell.fill) if target_cell.fill else None, "border": copy.copy(target_cell.border) if target_cell.border else None, "alignment": copy.copy(target_cell.alignment) if target_cell.alignment else None, } target_cell.value = value ``` The values reaching this sink are read directly from source CSV and XLSX files: ```python row_data[name] = row[col_idx].strip() if row[col_idx] else None ``` ```python cell = ws.cell(row=row, column=col) row_data[name] = cell.value if cell is not None else None ``` ### Technical Analysis The importer transfers attacker-controlled spreadsheet or CSV values into output workbook cells without checking whether a string is a formula. In particular, OpenPyXL treats strings beginning with `=` as formulas when the workbook is saved. An attacker can place a formula, external-reference formula, hyperlink formula, or DDE-style expression in a mapped source field. The importer preserves that expression as active workbook content instead of treating it as literal text. The vulnerability crosses a trust boundary: a source data file is treated as passive input, but its content can become executable spreadsheet syntax in a generated artifact. ### Attack Path 1. An attacker creates a CSV or XLSX source file containing a mapped value such as an external-reference or DDE-style formula beginning with `=`. 2. A user imports the file using the Skill. 3. `_load_csv()` ...[truncated 1105 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat imported strings as literal text by default. 2. Before assigning a source value, detect dangerous formula prefixes, especially `=`, and account for leading whitespace, tabs, and control characters. 3. Prefix untrusted formula-like strings with an apostrophe or explicitly store them as string cells. 4. Permit formulas only through an explicit configuration option that is disabled by default and limited to trusted source files. 5. Apply the same policy to CSV, XLSX, XLS, mapping defaults, headers, and any future import formats. 6. Add tests covering direct formulas, leading-whitespace formulas, external references, hyperlinks, and DDE-style payloads. 7. Warn users when formula-like input is rejected or neutralized. Example defensive logic: ```python def neutralize_formula(value): if not isinstance(value, str): return value normalized = value.lstrip("\t\r\n ") if normalized.startswith("="): return "'" + value return value ``` For stronger protection, reject formula-like values rather than modifying them when the affected field is expected to contain plain data. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/data_mapper.py:241
Finding
Unknown validation rules silently succeed<![CDATA[ ## Vulnerability Details **File Location**: `scripts/data_mapper.py:241-259` **Vulnerability Type**: Fail-open validation **Risk Level**: Medium ### Complete Code Snippet ```python elif validate_type == "regex": pattern = params.get("pattern") if pattern and re.match(pattern, str_value): return True, None msg = params.get("message", f"Format does not match: {str_value}") return False, msg elif validate_type == "length": min_len = params.get("min", 0) max_len = params.get("max") if min_len and len(str_value) < min_len: msg = params.get("message", f"Length cannot be less than {min_len}") return False, msg if max_len and len(str_value) > max_len: msg = params.get("message", f"Length cannot exceed {max_len}") return False, msg return True, None return True, None ``` The final `return True, None` is reached for every unrecognized validation type. ### Technical Analysis The validation dispatcher fails open. A misspelled, unsupported, or purportedly custom validation name is interpreted as successful validation rather than as a configuration error. This behavior is especially risky because `SKILL.md` advertises custom validators, while the implementation contains no controlled custom-validator registry. A user can therefore believe that a business or security rule is active even though the rule is silently skipped. Configuration validation in `scripts/config_parser.py` only checks that mappings contain `source` and `target`; it does not verify that the `validate` value is supported. ### Attack Path 1. A configuration uses an unsupported or misspelled validator, such as a purported custom business-rule validator. 2. The configuration passes `validate_config()`. 3. During record processing, `_write_record()` calls `validate_field()`. 4. No recognized validation branch matches the configured name. 5. `validate_field()` returns `(True, None)`. 6. The record is written even th ...[truncated 725 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define an explicit allowlist of supported validator names. 2. Reject unknown validators in `validate_config()` before any import begins. 3. Replace the fail-open default with an exception: ```python raise ValueError(f"Unsupported validation type: {validate_type}") ``` 4. If custom validators are required, implement a controlled registry rather than dynamic imports or `eval()`. 5. Require every registered validator to have a stable interface and explicit error behavior. 6. Add tests proving that unknown and misspelled validators stop the import. 7. Update documentation so that only implemented validation mechanisms are advertised. 8. Consider adding a strict schema for YAML configuration, including permitted validator names and parameter types. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/data_mapper.py:44
Finding
Documented encryption transform silently preserves sensitive plaintext<![CDATA[ ## Vulnerability Details **File Location**: `scripts/data_mapper.py:44-91` **Related Documentation**: `references/best-practices.md:352-361` **Vulnerability Type**: Silent failure of a sensitive-data protection control **Risk Level**: Medium ### Complete Code Snippet The transformation dispatcher ends by returning the original value for any unsupported transformation: ```python elif isinstance(value, (int, float)): if transform_type == "str": return str(value) elif transform_type == "int": return int(value) elif transform_type == "float": return float(value) return value ``` The documentation recommends the following unsupported configuration: ```yaml field_mappings: - source: "ID number" target: "ID number" transform: "encrypt" transform_params: algorithm: "aes" key: "your-secret-key" ``` No `encrypt` branch exists in `apply_transforms()`. ### Technical Analysis The documentation presents `encrypt` as a method for protecting sensitive fields, but the implementation does not support that transform. Unsupported transformations return the original value without an error or warning. As a result, a user following the documented security recommendation can generate a workbook containing unencrypted identity numbers or other sensitive data while reasonably believing the data was encrypted. This is a fail-open security-control problem rather than a cryptographic implementation weakness: the expected control is never applied, and the system gives no indication that it was skipped. The example also places key material directly in YAML. If encryption were implemented exactly as documented, that design would risk storing encryption keys alongside configuration and potentially in version control. ### Attack Path 1. A user follows the documented recommendation and configures `transform: "encrypt"` for a sensitive field. 2. `validate_config()` does not verify whether the transform is sup ...[truncated 956 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Immediately remove the unsupported encryption example unless encryption is implemented and tested. 2. Reject every unsupported transform during configuration validation. 3. If encryption is required, use authenticated encryption from a reviewed cryptographic library. 4. Do not place production encryption keys directly in YAML files. 5. Obtain key material from an approved secret manager, operating-system key store, or protected environment mechanism. 6. Separate keys from encrypted output and define rotation and recovery procedures. 7. Record which transformation was applied without logging sensitive source values or key material. 8. Add tests verifying that sensitive fields differ from plaintext in output and can only be decrypted with the intended key. 9. Make encryption failure fatal rather than falling back to plaintext. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/excel_import.py:68
Finding
Dry-run mode performs configuration-controlled filesystem writes<![CDATA[ ## Vulnerability Details **File Location**: `scripts/excel_import.py:68-95` **Additional Write Locations**: `scripts/excel_import.py:111-120, 486-502` **Vulnerability Type**: Unsafe preview-mode side effects **Risk Level**: Low ### Complete Code Snippet Initialization creates directories before dry-run behavior is considered: ```python self.dry_run = dry_run self.verbose = verbose self.no_backup = no_backup self._create_directories() ``` The called method creates configuration-controlled directories: ```python def _create_directories(self) -> None: output_path = Path(self.config["target"]["output_path"]).parent output_path.mkdir(parents=True, exist_ok=True) if self.config["error_handling"].get("backup", False): backup_path = Path( self.config["error_handling"].get("backup_path", "backup/") ) backup_path.mkdir(parents=True, exist_ok=True) log_path = Path( self.config["error_handling"].get("error_log_path", "logs/") ).parent log_path.mkdir(parents=True, exist_ok=True) ``` Backup and workbook loading also occur without a dry-run guard: ```python if ( self.config["error_handling"].get("backup", False) and not self.no_backup ): self._backup_target_file() self._load_workbooks() ``` A missing target is created and saved by `_load_workbooks()`: ```python if not target_path.exists(): self._create_target_template(target_path) self.target_wb.save(target_path) ``` ### Technical Analysis The command-line interface describes dry-run mode as a preview that performs no file writes. However, the importer creates output, backup, and log directories during object initialization. It may also copy the target into a backup location and create a new target workbook. All affected paths originate in YAML configuration and may be absolute or traverse outside the configuration directory. Although the actions run with the invoking user's existing privileges and do not eleva ...[truncated 1196 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make dry-run mode side-effect free. 2. Do not call `_create_directories()` during dry-run. 3. Guard backup, target creation, report generation, log creation, and workbook saving with `if not self.dry_run`. 4. In dry-run mode, create an in-memory workbook when a target template does not exist. 5. Resolve and validate every configured path before use. 6. Consider restricting relative paths to the configuration or workspace directory unless the user explicitly approves an external absolute path. 7. Add integration tests that snapshot the filesystem before and after dry-run and verify that no files, directories, or backups are created. 8. Document any unavoidable side effects explicitly rather than displaying a blanket “no writes” guarantee. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:21
Finding
Runtime dependencies are installed without version or integrity pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:21-22` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Low ### Complete Code Snippet ```markdown - **Required**: `pip3 install openpyxl pyyaml` - **Optional**: `pip3 install python-calamine` (for .xls legacy format) ``` A similar unpinned command appears in `references/quickstart.md:151`: ```bash pip install openpyxl pyyaml ``` ### Technical Analysis The installation instructions resolve mutable latest versions from the user's configured package index. The project does not provide a lock file, exact versions, or package hashes. The referenced package names are legitimate and no typosquatting package was identified. Therefore, this finding does not establish that a malicious dependency is currently present. The risk is that future installation behavior is not reproducible and depends on the current state and trustworthiness of the package index and dependency graph. Package installation and import can execute package-controlled code. A compromised future release, dependency account, index configuration, or transitive dependency could therefore affect the environment where the Skill runs. ### Attack Path 1. A user follows the documented installation command. 2. `pip` queries the user's configured package index. 3. The resolver selects the latest versions available at installation time. 4. A compromised, malicious, or unexpectedly incompatible release is downloaded and installed. 5. Package-controlled code executes during installation or when the importer loads the dependency. This attack path is contingent on supply-chain compromise or an untrusted package-index configuration; no such compromise was observed in the audited files. ### Impact Assessment Dependency code runs with the privileges of the user executing `pip` or the importer. If installation is performed in a privileged global environment, the potential scope increases accordingly. Possibl ...[truncated 290 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin reviewed dependency versions in a requirements or lock file. 2. Use package hashes, such as a hash-locked requirements file installed with `pip --require-hashes`. 3. Pin transitive dependencies where practical. 4. Perform installation in an isolated virtual environment rather than a privileged global environment. 5. Document the approved package index and avoid untrusted extra indexes. 6. Add automated dependency vulnerability and update monitoring. 7. Review and deliberately update pinned versions instead of automatically consuming the latest release. 8. Provide reproducible installation instructions, for example: ```bash python3 -m venv .venv . .venv/bin/activate python3 -m pip install --require-hashes -r requirements.txt ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (51)

Ae1

High
Category
analysis-evasion
Content
For full parameter docs, see [data-mapping-guide.md](references/data-mapping-guide.md).
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
For full parameter docs, see [data-mapping-guide.md](references/data-mapping-guide.md).
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- **Troubleshooting**: [troubleshooting.md](references/troubleshooting.md) — common issues
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Tool Parameter Abuse

High
Category
Tool Misuse
Content
df -h

# 清理临时文件
rm -rf /tmp/excel_import_temp_*

# 清理旧备份
find backup/ -name "*.xlsx" -mtime +30 -delete
Confidence
92% confidence
Finding
The guide recommends rm -rf /tmp/excel_import_temp_* as a cleanup step. Even though it targets a temp path, wildcard recursive deletion is error-prone and can remove unintended files if naming conventions, symlinks, or operator assumptions are wrong; in a spreadsheet import workflow this can destroy temporary evidence needed for troubleshooting or recovery.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
df -h

# 清理临时文件
rm -rf /tmp/excel_import_temp_*

# 清理旧备份
find backup/ -name "*.xlsx" -mtime +30 -delete
Confidence
92% confidence
Finding
The guide recommends rm -rf /tmp/excel_import_temp_* as a cleanup step. Even though it targets a temp path, wildcard recursive deletion is error-prone and can remove unintended files if naming conventions, symlinks, or operator assumptions are wrong; in a spreadsheet import workflow this can destroy temporary evidence needed for troubleshooting or recovery.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill instructs reading source files and writing output spreadsheets, but it does not declare any explicit tool scope or permissions boundaries. In an agent environment, this can lead to overbroad file access assumptions, making it easier for the skill to read or overwrite unintended files if invoked with attacker-controlled paths or ambiguous execution context.

Natural-Language Policy Violations

Medium
Confidence
85% confidence
Finding
The manifest description includes Chinese-only invocation guidance for when to use the skill, but the file does not state that the skill is region-specific or offer users a language/locale choice. This can violate organizational language/locale policy when a skill implicitly privileges one language without opt-in or justification.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire skill description and instructional content are written in Chinese, and there is no indication that users may choose another language or that the skill is intended only for a Chinese-speaking or region-specific context. This creates a natural-language policy concern because it effectively imposes a specific language without opt-in.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The example instructs users to drop rows, fill missing values, coerce parsing failures to NaN, and remove outliers without any warning that these steps irreversibly alter or delete source data semantics. In a data-import skill, users may apply the snippet to production spreadsheets and silently lose records or overwrite meaningful values, which can cause integrity issues and incorrect downstream business decisions.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This markdown file contains executable-style examples that scan a large directory of Excel files and write results to scan_results.json. The surrounding description presents the workflow as a solution, but does not warn users that running it will create output files and process potentially sensitive business data.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Later sections include examples that write errors_*.xlsx, processed/*.csv, checkpoint.json, import.log, and quality_report.png. Because this is a markdown skill/example file, the expected warning should tell users that executing these steps will persist transformed business data and diagnostic artifacts to disk.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The documentation explicitly states that when multiple source files contain the same key, later-processed files overwrite earlier data, but it does not prominently warn about unintended data loss or integrity issues. In a bulk spreadsheet import skill, silent overwrite behavior can cause users to corrupt or replace records at scale, especially when processing directories automatically.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This markdown file contains user-facing guidance entirely in Chinese and explicitly documents that the feature is primarily optimized for Chinese column names. That creates a language/locale constraint without opt-in or an alternative language path, which matches the policy category for forced language/locale behavior.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The document title and all instructional content are written in Chinese, and there is no indication that users may choose another language or that the locale restriction is intentional and justified. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
```yaml
options:
  preserve_formatting: false     # 不保持格式,提升速度
  skip_validation: true          # 跳过验证(谨慎使用)
```

### 2. 批量文件处理
Confidence
90% confidence
Finding
The best-practices document presents 'skip_validation: true' as a performance optimization option, which can encourage disabling integrity checks during import. In this skill context, validation is a primary safeguard against malformed, inconsistent, or maliciously crafted spreadsheet data, so recommending it without stronger constraints increases risk of bad data ingestion and downstream corruption.

Ssd 3

Medium
Confidence
96% confidence
Finding
The error log example includes raw sensitive values such as an ID number field and corresponding value, which normalizes logging plaintext personal data. In an Excel import workflow that processes HR-style records and identity data, this increases the chance of privacy leakage through log files, backups, and downstream log aggregation systems.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**文件权限**:
```bash
# 配置文件: 只读
chmod 444 import_config.yaml

# 备份目录: 仅所有者可写
chmod 700 backup/
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
chmod 444 import_config.yaml

# 备份目录: 仅所有者可写
chmod 700 backup/

# 错误日志: 仅所有者可读写
chmod 600 logs/import_errors.log
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
chmod 700 backup/

# 错误日志: 仅所有者可读写
chmod 600 logs/import_errors.log
```

### 3. 数据备份策略
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The guide uses examples with highly sensitive personal data such as ID numbers and phone numbers, but does not warn users about privacy, minimization, masking, or compliance obligations. In a data-import skill, this can normalize unsafe handling of PII and lead users to process real sensitive data in configs, test files, and logs without safeguards.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The debugging and preview examples print raw mapped values directly to console output, including fields like name, ID card number, and phone number. In this skill’s context, those examples are likely to be copied into real workflows, causing sensitive data exposure through terminals, logs, CI output, shared screenshots, or support bundles.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The document states that target files will be modified and backup copies created automatically, but it does not explicitly warn users about these side effects or the storage implications of backup/rollback behavior. In a file-import skill that operates on spreadsheets, this can lead to unintended data duplication, unexpected persistence of sensitive data in backup folders, and user surprise about destructive or state-changing actions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The validation report example includes a national ID field and raw sample value, while the logging/reporting guidance does not warn about exposure of personally sensitive data in logs or exported JSON reports. In this skill's context, import errors are likely to involve real spreadsheet records, so logging field values can create secondary privacy leakage through log files, reports, and backups.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The quickstart uses realistic-looking Chinese national ID numbers and demonstrates exporting and backing up personal data to output files without any warning about handling sensitive PII, masking examples, or safe storage practices. In a data-import skill specifically designed to process spreadsheets at scale, this can normalize unsafe handling of real personal data and increase the chance that users copy the pattern into production with unprotected identifiers and duplicated backups.

File System Enumeration

Medium
Category
Data Exfiltration
Content
**调试命令**:
```bash
# 检查文件是否存在
ls -l /home/user/project/data/data.xlsx

# 检查当前工作目录
pwd
Confidence
60% confidence
Finding
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Static analysis

No suspicious patterns detected.