Back to skill

Security audit

Heath Ledger

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent bookkeeping software, but it needs review because it stores bank and Stripe credentials plus detailed financial data locally in plaintext and exposes transaction details through command output/AI workflows.

Review before installing. Use only restricted/read-only Mercury and Stripe credentials, avoid passing long-lived secrets directly on the command line, and assume data/heath.db plus generated Excel files contain sensitive financial records and stored API keys. Install only in a secured local workspace, protect or delete the data directory when done, and rotate any credentials used with this version.

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/connect_mercury.mjs:5
Finding

API Credentials Exposed Through Command-Line Arguments and Plaintext SQLite Storage

Content
View full analysis
[entity_name]'); process.exit(1); } ``` `scripts/connect_mercury.mjs:31-32`: ```js // Create connection (store token as-is locally — no encryption needed for local SQLite) const connResult = db.prepare('INSERT INTO connections (entity_id, provider, access_token) VALUES (?, ?, ?) RETURNING id').get(entityId, 'mercury', token); ``` `scripts/connect_stripe.mjs:5-10`: ```js const entityId = process.argv[2]; const apiKey = process.argv[3]; if (!entityId || !apiKey) { console.error('Usage: connect_stripe.mjs '); process.exit(1); } ``` `scripts/connect_stripe.mjs:28-36`: ```js const existing = db.prepare('SELECT id FROM connections WHERE entity_id = ? AND provider = ?').get(Number(entityId), 'stripe'); let connectionId; if (existing) { db.prepare('UPDATE connections SET access_token = ?, updated_at = datetime(\'now\') WHERE id = ?').run(apiKey, existing.id); connectionId = existing.id; console.log(` Updated existing Stripe connection (id: ${connectionId})`); } else { const result = db.prepare('INSERT INTO connections (entity_id, provider, access_token) VALUES (?, ?, ?) RETURNING id').get(Number(entityId), 'stripe', apiKey); ``` `scripts/lib/db.js:7-8, 13-15`: ```js const DATA_DIR = join(SKILL_DIR, 'data'); const DB_PATH = join(DATA_DIR, 'heath.db'); let _db = null; export function getDb() { if (_db) return _db; mkdirSync(DATA_DIR, { recursive: true }); _db = new Database(DB_PATH); ``` `scripts/l ...[truncated 3159 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description describes a full bookkeeping system with Mercury integration, transaction categorization, and report generation. The actual supplied code chunk only contains a small shell script that delegates execution to add_rule.mjs. From this chunk alone, none of the core declared capabilities are represented. Instead, the visible behavior suggests a narrower purpose related to adding rules. Because the observed code does not substantiate the stated primary purpose and points to a different operational focus, this is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

There is a clear mismatch between the declared purpose and the supplied code. The description focuses on Mercury bank bookkeeping workflows: pulling and categorizing transactions and generating P&L, balance sheet, cash flow, and books. The actual code only launches a Node script named connect_stripe.mjs, which strongly suggests Stripe integration. Nothing in the provided chunk reflects Mercury access, bookkeeping logic, categorization, or report/workbook generation. This is a materially different primary purpose and resource target.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a finance/bookkeeping skill focused on Mercury bank transaction ingestion, categorization, and workbook/report generation. The actual code chunk only launches a database initialization script, which is an infrastructure/setup action. While setup code can be a supporting detail, this snippet by itself does not implement or directly reflect the declared bookkeeping functionality, and its primary observable purpose is materially different from the declared end-user capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description centers on Mercury bank bookkeeping: pulling bank transactions, categorizing them, and producing accounting workbooks and financial statements. The supplied code instead connects to Stripe's API (https://api.stripe.com/v1), retrieves balance transactions, paginates through them, filters charge/payment/refund records, and computes revenue, refund, fee, and net revenue summaries. This is a materially different data source and purpose. While both relate broadly to financial data, the actual behavior is Stripe payments revenue reporting, not Mercury bank bookkeeping or statement generation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full bookkeeping/financial reporting skill focused on Mercury bank data. However, the supplied code chunk only shows a minimal shell script delegating execution to a Node script called list_entities.mjs. From the visible code, the primary observable behavior is launching an entity-listing script, which is materially different from the declared bookkeeping functionality. Because the visible behavior does not align with the stated purpose and instead suggests an unrelated capability, this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description centers on a Mercury bookkeeping workflow: pulling bank transactions, categorizing them, and generating accounting workbooks and financial statements. The actual code chunk is only a wrapper that executes a Node script explicitly named pull_stripe_revenue.mjs. From the name and invocation, the observable behavior is oriented toward pulling Stripe revenue data, which is a different financial source and a narrower function than the declared Mercury bookkeeping agent. There is no evidence in this chunk of Mercury connectivity, categorization logic, or workbook/statement generation. Therefore, the code does not accurately match the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full-featured bookkeeping agent with transaction ingestion, categorization, and financial statement generation. The supplied code chunk, however, only launches another script called set_category.mjs and does not itself demonstrate any of those broader capabilities. Based on the visible behavior, the primary purpose looks like a narrow helper for setting categories, not a complete Mercury bookkeeping and reporting system. Because the observed code is materially narrower and different from the declared purpose, this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full bookkeeping workflow centered on Mercury bank data ingestion, categorization, and generation of accounting workbooks. The supplied code chunk, however, contains only a minimal shell script that invokes status.mjs. There is no visible logic related to bank APIs, bookkeeping, AI categorization, Excel creation, or financial statements. While this wrapper may be part of a larger system, based solely on the supplied code it does not substantiate the declared purpose and instead indicates a different immediate function: running a status command.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes an AI bookkeeping agent for Mercury bank accounts, including connecting Mercury and producing books from Mercury transactions. This script instead connects to Stripe, validates a Stripe API key, and stores a Stripe provider connection, which is a materially different financial integration not disclosed by the skill description.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/lib/categorization.js (reported line 112)May include surrounding context.

js
// Increment usage count
  db.prepare('UPDATE categorization_rules SET usage_count = usage_count + 1 WHERE id = ?').run(rule.id);
  
  return rule;
}

/**

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This file implements direct access to Stripe financial data even though the skill is described as Mercury-only bookkeeping. That scope mismatch is dangerous because it expands the agent's effective access to additional financial systems and sensitive transaction data without clear user expectation or documented justification, increasing the risk of unauthorized data collection or misuse.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==1.1.12 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
93% confidence
Finding

brace-expansion 1.1.12 is flagged with multiple high-severity DoS-style advisories involving pathological brace patterns that can trigger excessive CPU or memory use. In this lockfile it is only a transitive dependency, so exploitability depends on whether attacker-controlled glob or pattern input reaches code paths using minimatch/glob, but the dependency presence itself is real and should be treated as a supply-chain risk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==3.1.3 — 1 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu)

High
Category
Supply Chain
Confidence
92% confidence
Finding

minimatch 3.1.3 has a reported ReDoS issue where crafted extglob patterns can cause catastrophic backtracking and process slowdown. This is especially relevant in Node services that accept user-influenced file patterns, and bookkeeping/report-generation tooling may process imported filenames, archive contents, or template patterns, making denial of service plausible if such input is exposed.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

brace-expansion 2.0.2 is another vulnerable instance with multiple DoS advisories, separate from the older 1.x copy. Having multiple vulnerable copies increases attack surface because either dependency path could be exercised by archive or file-discovery functionality used by Excel/report tooling.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==5.1.7 — 2 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
94% confidence
Finding

minimatch 5.1.7 is flagged for multiple ReDoS issues, meaning crafted match patterns can consume disproportionate CPU. Because this package appears in transitive file enumeration logic, an attacker may be able to abuse imported archive names, glob-like filters, or other pattern-based processing to degrade service availability.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: tmp==0.2.5 — 1 advisory(ies): CVE-2026-44705 (tmp has Path Traversal via unsanitized prefix/postfix that enables directory esc)

High
Category
Supply Chain
Confidence
89% confidence
Finding

tmp 0.2.5 is reported with a path traversal issue via unsanitized prefix/postfix handling, which can allow creation of temporary files or directories outside intended locations when attacker-controlled path components are used. In a bookkeeping skill that generates Excel workbooks and may handle imported/exported files, unsafe temp-file creation is more dangerous because it can affect sensitive financial data, overwrite files, or bypass expected filesystem boundaries.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes network-capable operations against Mercury and Stripe APIs but does not declare any explicit tool scope, permissions, or allowed-tools constraints. In an agent environment, that omission increases the chance of over-broad tool access and unintended external requests involving highly sensitive financial data and API tokens.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The invocation text is broad and can trigger on generic bookkeeping intents without clear exclusions, data handling boundaries, or preconditions. In practice, this can cause the skill to activate in contexts involving sensitive financial records or credentials when a narrower tool would suffice, increasing unnecessary exposure of banking and accounting data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation states that books are generated and stored locally but does not prominently warn that these outputs may contain highly sensitive financial statements, transaction details, and account-linked business data. Users or agents may therefore write confidential data to insecure locations, shared workspaces, or retained artifacts without realizing the exposure risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code serializes uncategorized bank transactions, including counterparty names, descriptions, and amounts, to stdout specifically for downstream AI processing, but it provides no consent gate, redaction, or user-facing disclosure that sensitive financial data is being exposed outside the local rules engine. In a bookkeeping skill handling Mercury bank data, this creates a real confidentiality risk because stdout is commonly captured by host agents, logs, pipelines, or third-party model integrations, potentially disclosing highly sensitive financial records.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script persists a Mercury API token in plaintext in a local SQLite database and explicitly dismisses encryption as unnecessary. Mercury tokens grant access to sensitive financial data, so compromise of the workstation, repository artifacts, backups, or the database file could expose banking data and enable unauthorized API access. In a bookkeeping skill, this is especially dangerous because the stored credential directly protects financial accounts and statements.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script stores a high-value API credential without clearly warning the user or obtaining confirmation that it will be retained locally. This increases the chance that users will unknowingly leave long-lived bank access tokens on disk, where they may be captured through backups, shared environments, malware, or later local compromise. The bookkeeping context raises the risk because the credential provides access to sensitive Mercury banking information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script prints transaction dates, counterparties, categories, and amounts directly from bookkeeping spreadsheets to stdout. In a bookkeeping skill, this data is highly sensitive financial information, and logging it can leak customer/vendor relationships and transaction details into terminal history, CI logs, or centralized log collectors without any access controls or warning.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code creates a local data directory and opens a persistent SQLite database, then initializes multiple tables containing potentially sensitive financial and access-token data. There is no confirmation prompt, user-facing log, or inline warning indicating that the skill will write persistent data to disk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes an AI bookkeeping agent for Mercury bank accounts that pulls transactions, categorizes them, and generates financial statements. This schema adds a dedicated stripe_monthly_revenue table, indicating first-class support for Stripe revenue ingestion and storage, which is a distinct integration/capability not disclosed by the Mercury-focused description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.