Back to skill

Security audit

Bank Statement Reconciler

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a real bank-statement reconciler, but it should be reviewed carefully because it handles sensitive financial files and has concrete accuracy and spreadsheet-export safety risks.

Install only if you are comfortable reviewing and controlling how sensitive bank, customer, invoice, and order data is processed. Avoid opening generated spreadsheets from untrusted inputs until formula neutralization is added, verify reconciliation results manually for duplicate or repeated amounts, and require explicit approval before sharing any output to Feishu or another external service.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/tier_config.py:48
Finding

Paid Feature Authorization Can Be Forged Using Arbitrary Token Prefixes or Caller-Controlled Overrides

Content
View full analysis
str: """Detect tier from token prefix or plan_id.""" if not self.token: return "FREE" token_upper = self.token.upper() for tier_name, prefix in TOKEN_PREFIXES.items(): if token_upper.startswith(prefix): return tier_name return "FREE" ``` The explicit token validation is also limited to a prefix comparison: ```python def validate_token(self, token: str) -> bool: """Validate that token matches expected prefix for tier.""" if not token: return True # No token = Free tier token_upper = token.upper() expected_prefix = TOKEN_PREFIXES.get(self.tier_name, "") if not expected_prefix: return True return token_upper.startswith(expected_prefix) ``` The resulting caller-controlled entitlement is trusted when paid functionality is enabled: ```python # Export Excel if tier supports excel_path = None if tier.can_export_excel() and (result["matched"] or result["differences"] or result["unclaimed"] or result["unmatched_orders"]): exporter = ReconciliationExporter() excel_path = exporter.export(result) result["excel_path"] = excel_path ``` ### Technical Analysis The subscription token is not authenticated, cryptographically verified, or checked against a trusted subscription service. A token is accepted solely because its text starts with a known string such as `BANK-PRO` or `BANK-ENT`. Additionally, the constructor accepts `tier_name` and `is_pro` directly from the caller. These values override or supplement token-derive ...[truncated 1890 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/exporter.py:119
Finding

Attacker-Controlled Reconciliation Data Is Exported Without Spreadsheet Formula Neutralization

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/matcher.py:54
Finding

Matching Algorithm Does Not Enforce One-to-One Transaction and Order Pairing

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

The supplied code is a parser layer, not a full bank statement reconciler. It supports many of the declared input sources and file types, including Chinese banks, Alipay/WeChat, PayPal/Stripe, and Amazon/Shopify/Temu, which aligns partially with the description. However, the core declared purpose is reconciliation via AI auto-matching between statements and orders/invoices, producing categorized reconciliation outcomes. None of that logic appears in the code chunk: there is no record matching, tolerance handling, invoice-to-payment linking, discrepancy detection, or output classification. The subprocess PDF parsing call is consistent with document parsing and not an undeclared concerning capability. Therefore this is a material description-behavior mismatch: the code implements ingestion/parsing support for a reconciler, not the reconciler itself.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README promotes uploading bank statements, orders, invoices, and exporting reconciliation results, but provides no warning about handling highly sensitive financial and personal data. In a skill centered on financial reconciliation, this omission increases the chance users will process real production data without understanding storage, sharing, redaction, or access-control risks, which can lead to data exposure through files, exports, logs, or downstream integrations like Feishu.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill documentation describes capabilities that imply reading uploaded files, exporting Excel files, and possibly invoking code paths, but it does not declare any explicit tool scope or permissions. In a financial-document workflow, this gap weakens security boundaries because an agent may be granted broader file or execution access than users expect, increasing the chance of over-privileged handling of sensitive bank data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is centered on ingesting bank statements, invoices, and orders, then exporting reconciliation files, yet it provides no warning about the sensitivity of those documents or the risks of storing derived outputs. In this context, missing privacy and handling guidance is especially dangerous because the data likely includes bank account details, counterparties, balances, transaction histories, and business records that require strict protection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill promotes pushing reconciliation results to Feishu without any warning, consent step, or data-minimization guidance. Because reconciliation outputs can contain highly sensitive financial and customer information, silent transmission to a third-party messaging platform can cause confidentiality breaches, regulatory exposure, and accidental disclosure to unintended recipients.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code hard-codes Chinese sheet titles and user-visible labels such as "汇总" and "对账汇总", and the same pattern continues throughout the exporter. Because the file provides no opt-in, language selection, or documented region-specific justification, it violates the language/locale policy criteria for natural-language content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code builds all user-visible Feishu card and message content in Chinese, such as the title and later status labels, but provides no option for users to select a language and no comment indicating the skill is intentionally limited to a Chinese-speaking audience. That creates a natural-language policy concern because the skill effectively forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code assigns the Chinese string "待处理" as the status value for unmatched transactions and orders. This forces a specific language in user-visible output, and the file does not offer locale selection or explain a region-specific requirement that would justify the restriction.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill is described as uploading and parsing bank statements/orders for reconciliation, but the PDF path shells out to an external executable via subprocess. Spawning local commands is a materially broader capability than straightforward file parsing and is not declared in the manifest description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code sends the provided PDF file path to an external CLI via subprocess for parsing, which is a safety-relevant operation on code files. Although the docstring says it parses PDF files, there is no confirmation prompt, visible logging/print, or explicit warning that an external command will be executed on the user's document.

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/parser.py (reported line 249)May include surrounding context.

python
"""Parse PDF file using doc_parse."""
        import subprocess
        
        result = subprocess.run(
            ["miaoda-studio-cli", "doc-parse", "--file", filepath, "--output", "text"],
            capture_output=True, text=True, timeout=60
        )

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/parser.py (reported line 532)May include surrounding context.

python
"""Parse PDF file using doc_parse."""
        import subprocess
        
        result = subprocess.run(
            ["miaoda-studio-cli", "doc-parse", "--file", filepath, "--output", "text"],
            capture_output=True, text=True, timeout=60
        )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This order parser repeats the same pattern of calling an external CLI through subprocess on a user-provided PDF file. The operation is not accompanied by a confirmation prompt, visible user disclosure, or comment/docstring explaining that an external tool will be launched to process the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The feature list explicitly emphasizes Chinese banks and payment platforms, which can imply a locale-specific constraint in the skill's supported usage. Because the documentation does not explain whether this is an intentional region-scoped tool or how non-Chinese users should interpret the limitation, it may conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.