Back to skill

Security audit

发票报销助手

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a local invoice manager, but it handles sensitive reimbursement records with under-disclosed network exposure and unsafe destructive/report-export behavior.

Review before installing. Use only with invoice data you are comfortable storing locally, avoid opening generated reports or CSVs from untrusted invoice inputs, and treat delete/force-add operations as potentially irreversible. The publisher should remove or justify web permissions, disclose the CDN dependency, add confirmation or recovery for destructive actions, and escape report/CSV output before this is suitable for sensitive reimbursement workflows.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report_generator.py:315
Finding

Stored Cross-Site Scripting in Generated HTML Reports

Content
View full analysis
{inv['id']}{inv['invoice_date']} {cat_icon} {inv['category']}{inv['invoice_type'][:10]} ¥{inv['total_amount']:,.2f} {inv['seller_name'][:15]} {status_label} """ ``` ```python "__INVOICES_JSON__": json.dumps(invoices, ensure_ascii=False, default=str), ``` ```javascript checks.forEach(function(c) { var inv = invoices.find(function(i) { return i.id == parseInt(c.dataset.id); }); if (!inv) return; total += inv.total_amount; var icon = CATEGORY_ICONS[inv.category] || '📋'; itemsDiv.innerHTML += '
' + '' + icon + ' ' + inv.invoice_date + ' | ' + inv.category + ' | ' + (inv.seller_name||'').substring(0,20) + '' + '¥' + inv.total_amount.toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '
'; }); ``` ```javascript var itemsHtml = selectedInvoices.map(function(i) { var icon = CATEGORY_ICONS[i.category] || '📋'; return '' + i.invoice_date + '' + icon + ' ' + i.category + '' + i.invoice_number + '' + (i.seller_name||'') + '¥' + i.total_amount.toFixed(2) + ''; }).join(''); var notesHtml = notes ? '

备注: ' + notes + '

' : ''; var doc = window.open('', '_blank', 'width=800,height=600'); doc.doc ...[truncated 3476 chars]
Remediation
View remediation
... ``` Escape `<`, `>`, `&`, U+2028, and U+2029 before embedding, then parse the element's `textContent`. 4. Validate enumerated fields such as category and status against strict server-side allowlists. 5. Escape reimbursement reason and notes before placing them in a printable document. 6. Add a restrictive Content Security Policy that disallows inline scripts and unauthorized network destinations. 7. Add regression tests using payloads containing HTML attributes, event handlers, quotes, and ``. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/invoice_manager.py:329
Finding

Spreadsheet Formula Injection and Improper CSV Escaping

Content
View full analysis
0 ? invoices.filter(function(i) { return ids.indexOf(i.id) >= 0; }) : invoices; var csv = 'ID,发票代码,发票号码,日期,类型,类别,金额,税额,价税合计,销售方,状态\n'; selectedInvoices.forEach(function(i) { csv += i.id + ',' + i.invoice_code + ',' + i.invoice_number + ',' + i.invoice_date + ',' + i.invoice_type + ',' + i.category + ',' + i.amount + ',' + i.tax_amount + ',' + i.total_amount + ',"' + (i.seller_name||'') + '",' + i.status + '\n'; }); var blob = new Blob(['\ufeff' + csv], {type: 'text/csv;charset=utf-8;'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = '报销明细_' + new Date().toISOString().slice(0,10) + '.csv'; a.click(); URL.revokeObjectURL(url); showToast('CSV导出成功!', 'success'); } ``` ### Technical Analysis User-controlled invoice values are exported without neutralizing spreadsheet formula prefixes. Spreadsheet applications may interpret cells beginning with `=`, `+`, `-`, or `@` as formulas, even when the value is enclosed in CSV quotes. The Python exporter correctly uses the standard CSV writer for structural quo ...[truncated 1566 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/invoice_manager.py:426
Finding

Force-Add Option Silently Deletes an Existing Invoice

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/report_generator.py:46
Finding

Generated Reports Execute Third-Party JavaScript Without Integrity Protection

Content
View full analysis
``` The project documentation states that reports use plain HTML, CSS, and JavaScript without an external service and that data remains local, but generated reports contact jsDelivr when opened. ### Technical Analysis Every generated HTML report downloads and executes Chart.js from a third-party CDN at runtime. The URL pins a package version, but the script element does not include a Subresource Integrity hash. Consequently, the browser trusts executable content delivered by the CDN and network path at the time the report is opened. This also means the report is not fully offline. Although the project code does not explicitly transmit invoice data to the CDN, the remote script executes in the same page context as the full invoice dataset. ### Attack Path 1. A user generates an HTML invoice report. 2. The user opens the report while connected to a network. 3. The browser requests Chart.js from `cdn.jsdelivr.net`. 4. The externally delivered script executes in the report context. 5. If the dependency delivery path is compromised or serves altered content, that code can access the invoice data embedded in the page and perform browser-permitted network actions. ### Impact Assessment A compromised dependency could execute arbitrary JavaScript in the generated report and obtain access to all invoice records embedded in that page. It could alter displayed totals or transmit data to external services subject to browser policy. The finding does not demonstrate that jsDelivr or Chart.js is malicious. The risk arises from executing third-party runtime code without local bundling, integrity verification, or an accurate disclosure of the network dependency. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

该描述与代码部分匹配:代码确实支持发票录入、查询、删除、导出、查重,以及基于关键词的简单费用分类和统计汇总。但描述中的两个核心卖点没有在该代码块中体现:1)“上传发票图片自动识别关键信息”——代码仅存储image_path字段,没有任何图像处理、OCR或解析逻辑;2)“生成可视化HTML报销报告”——代码只实现CSV导出、JSON汇总和CLI打印,没有HTML生成功能。另一个轻微不一致是代码还支持更新发票信息,而声明只提到录入/查询/删除/导出。综合看,声明把技能描述为更完整、更智能的发票识别与报销报告助手,而实际代码是发票数据管理后端的一部分,因此应判定为存在描述与行为不一致。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Broad triggers such as everyday invoice-related phrases can cause unintended activation, leading the skill to handle or modify reimbursement data when the user did not clearly intend to invoke it. In a skill with read/write/delete capabilities over financial records, accidental invocation raises the risk of privacy exposure and unintended state changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Advertising deletion capability without an explicit warning or confirmation model is dangerous because users may not appreciate that the skill can permanently remove reimbursement records. In the context of financial record management, destructive actions can cause data loss, audit gaps, and operational disruption.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill asserts local-only handling of invoice data, but the manifest grants WebFetch and WebSearch, creating an unnecessary path for outbound transmission of sensitive financial and personal data. Even if the current documentation says data stays local, these extra capabilities expand the attack surface and weaken user trust and containment guarantees.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

For a documented local invoice reimbursement assistant, network access is unjustified and increases the risk of unintended data leakage or future misuse. Invoice records commonly contain names, vendors, dates, amounts, and identifiers, so unnecessary outbound capability is security-significant in this context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The command example shows direct deletion of invoice data with no warning, preview, or confirmation note, normalizing unsafe destructive behavior. Because reimbursement records may be business-critical, users could copy this pattern and irreversibly remove data without safeguards.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation explicitly promises that all data remains local and is never uploaded, yet the manifest enables external web access. This contradiction is dangerous because users may provide sensitive invoice data under a false privacy assumption, while the granted capability would technically allow exfiltration.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The inline help text for '--force' says '强制录入(跳过查重)', which implies bypassing duplicate detection. In reality, when '--force' is used the code deletes any existing invoice with the same number/code before calling add_invoice(), so the behavior is destructive replacement rather than merely skipping a duplicate check.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Force-add mode deletes existing invoice records matching invoice_number and invoice_code with no confirmation, audit trail, or soft-delete protection. In a reimbursement workflow, this can silently destroy financial records and enable accidental or intentional tampering with expense evidence, especially if exposed through an agent or automation layer.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s docstring and generated UI/report content consistently force Chinese-language labels and the zh-CN locale, including HTML lang attributes and locale-specific date/number formatting. The policy allows locale constraints only when the skill offers user opt-in or clearly documents a justified region-specific restriction, neither of which appears here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

文件文档和函数说明将该模块表述为“生成交互式HTML可视化报告”与“报告生成器”,但模板中包含“批量标记已审批”“标记已报销”“生成报销单”等面向业务操作的界面与流程元素。尽管当前实现中的状态更新仅展示提示而未真正持久化,这仍超出了单纯报告生成的语义范围,与该文件宣称职责存在明显偏差。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated report loads Chart.js from a third-party CDN, which introduces unnecessary outbound network dependency into a local invoice-processing workflow. If the CDN content is compromised, blocked, or modified in transit, opening the report could execute attacker-controlled JavaScript in the context of a page containing sensitive invoice data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The module docstring and CLI help text are written in Chinese, and there is no indication that users can select another language or that the language restriction is intentional and documented. This can conflict with language/locale policy expectations when a skill effectively forces one language for interaction.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.