Back to skill

Security audit

Generate Alipay WeChat Report

Security checks for vulnerabilities and agentic risk

Overview

This local bill-report skill mostly does what it claims, but its generated HTML can run attacker-crafted script from transaction text and expose sensitive spending data.

Install only if you are comfortable processing sensitive payment exports locally and can keep the input directory narrow. Until the HTML serialization is fixed, avoid using --open on reports generated from untrusted or unusual transaction data, do not host or share the generated report, and treat the HTML as containing private financial information.

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

Error
Location
scripts/generate_spending_report.py:1238
Finding

Stored Script Injection Through Unescaped Transaction Data in the Generated HTML Report

Content
View full analysis
const report = __PAYLOAD__; const poolKeys = ["all", "consumption", "habit"]; let currentPool = "habit"; ``` The placeholder is replaced with the result of `json.dumps()` without HTML-context escaping: ```python normalized = template.replace("{{", "{").replace("}}", "}") return normalized.replace("__PAYLOAD__", payload_json) def generate_report(alipay_path: Path, wechat_path: Path, output_path: Path) -> Path: transactions = [transaction for transaction in parse_alipay(alipay_path) + parse_wechat(wechat_path) if keep_spend(transaction)] report = build_report_payload(transactions, alipay_path, wechat_path) output_path.parent.mkdir(parents=True, exist_ok=True) output_path.write_text(html_template(json.dumps(report, ensure_ascii=False)), encoding="utf-8") return output_path ``` ### Technical Analysis Merchant names, item descriptions, notes, payment methods, and other transaction-derived strings are attacker-influenced data. These values are serialized using `json.dumps()` and inserted directly into an HTML `< ...[truncated 2470 chars]
Remediation
View remediation
str: return ( json.dumps(value, ensure_ascii=False) .replace("&", "\\u0026") .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("\u2028", "\\u2028") .replace("\u2029", "\\u2029") ) ``` Use it when generating the report: ```python payload_json = safe_json_for_html(report) output_path.write_text(html_template(payload_json), encoding="utf-8") ``` 2. Prefer separating data from executable JavaScript: ```html ``` The JSON must still escape `<` as `\u003c`, because the HTML parser recognizes `` regardless of the script element’s MIME type. 3. Avoid constructing report markup with `innerHTML` where practical. Create elements with `document.createElement()` and assign transaction-derived values through `textContent`. 4. Add a restrictive Content Security Policy. Move the dashboard JavaScript into a separately generated or static script and disallow inline scripts where feasible: ```html ``` For a fully self-contained report, use a nonce or hash-based policy instead of broadly allowing all inline scripts. 5. Add regression tests with transaction fields containing payloads such as: ```text <>& ``` Verify that the generated HTML contains `\u003c/script\u003e`, that no additional executable script element is create ...[truncated 71 chars]
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 16)May include surrounding context.

md
2. Use `scripts/generate_spending_report.py` to build the report.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to read local billing files, write an HTML report, and invoke Python via shell, but it declares no explicit tool scope or permission boundaries. Without scoped permissions, an agent runtime may grant broader-than-necessary file and shell access, increasing the chance of unintended file access, overwrites, or command misuse when handling sensitive financial data.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/generate_spending_report.py (reported line 1260)May include surrounding context.

python
if args.open:
        import subprocess

        subprocess.run(["open", str(output_path)], check=False)


if __name__ == "__main__":

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language default prompt is written as an imperative in English despite the skill metadata being Chinese, which suggests the skill may force an English-language interaction or invocation format without offering a language choice. This matches the policy category for language or locale constraints that are imposed without explicit user opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill's stated purpose is to transform local Alipay/WeChat export files into a local HTML spending report. The optional --open path invokes subprocess.run to launch the generated file via the system open command, which is not necessary for generating the report itself and introduces executable capability beyond the core analytics context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.