Back to skill

Security audit

Local Budget

Security checks for vulnerabilities and agentic risk

Overview

This is a real local budgeting helper, but it should be reviewed because it saves sensitive financial files and can put untrusted transaction text directly into Markdown reports.

Use this only for bank exports you intend to process locally, keep generated JSON and Markdown in a private folder, and review categories before relying on the report. Be cautious opening generated reports in Obsidian or another Markdown viewer if imported CSV or JSON data could be untrusted; keep remote content loading disabled and treat outputs as sensitive financial records.

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

Warning
Location
scripts/report.py:187
Finding

Unescaped Transaction Data Enables Markdown Content Injection and Potential Privacy Leakage

Content
View full analysis
0: remaining = monthly_budget - spent pct = spent / monthly_budget * 100 pct_str = f"{pct:.0f}%" remaining_str = fmt_currency(remaining) if remaining >= 0 else f"**-{fmt_currency(abs(remaining))}**" alert = "⚠️" if spent > monthly_budget else ("🔶" if pct >= 80 else "✅") bar = bar_chart(spent, monthly_budget) lines.append(f"| {category} | {fmt_currency(spent)} | {fmt_currency(monthly_budget)} | {remaining_str} | {pct_str} | {alert} {bar} |") else: lines.append(f"| {category} | {fmt_currency(spent)} | — | — | — | — |") else: pct = fmt_pct(spent, stats["total_spent"]) lines.append(f"| {category} | {fmt_currency(spent)} | {pct} |") lines.append("") # Budget alerts if budget: overages = [] warnings = [] for category, monthly_b ...[truncated 4312 chars]
Remediation
View remediation
str: text = str(value) text = text.replace("\\", "\\\\") text = text.replace("|", "\\|") text = text.replace("\r", " ").replace("\n", " ") text = text.replace("<", "<").replace(">", ">") return text ``` 2. Apply the escaping function to all transaction-derived and configuration-derived fields before interpolation, including: - Merchant descriptions - Categories - Month labels derived from input dates - Budget category names - Source filenames 3. Neutralize Markdown image and link syntax where practical. For merchant and category labels, consider rendering escaped inline code rather than unrestricted Markdown. 4. Reject or normalize control characters during CSV and JSON ingestion. Newlines, carriage returns, null bytes, and other non-printable characters should not be retained in descriptions or categories. 5. Serialize YAML frontmatter with a proper YAML library or strictly sanitize and quote all values inserted into frontmatter. The source filename and month values should not be interpolated as raw YAML. 6. Add security regression tests using values such as: ```text ![](https://attacker.example/track) [Click here](https://attacker.example/) Merchant | Injected column Merchant ## Fabricated Section ``` The tests should verify that these values render only as inert text and cannot create links, images, HTML elements, new rows, or new sections. 7. Document that imported CSV and JSON files are untrusted inputs. As defense in depth, advise users to keep remote resource loading disabled in their Markdown viewer. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code only implements CSV parsing and normalization into JSON. It reads local CSV files, auto-detects some bank formats, cleans dates and amounts, labels entries as debit/credit, and outputs JSON. This is consistent with part of the declared workflow involving bank/credit card CSV handling and local/private processing, but it does not implement the core declared capabilities of spending analysis, LLM-based categorization, budget comparison, or markdown report generation. The primary purpose of this code chunk is ingestion/parsing rather than end-user finance analysis, so the description overstates what this code actually does.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the agent to write JSON and markdown outputs to user-chosen locations, including an Obsidian vault, but it declares no explicit tool scope or file access restrictions. In an agent environment, missing permission boundaries can allow broader-than-expected file writes if the skill is auto-invoked or used with untrusted paths.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger phrases are broad enough to match ordinary financial conversation such as budgeting, spending, or monthly expenses, which can cause the skill to activate in contexts the user did not intend. Because the skill processes highly sensitive financial data and may write reports to disk, overbroad activation increases privacy and safety risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest says the skill categorizes transactions with LLM reasoning, but this reference document states categorization is performed via regex keyword matching and that only low/medium-confidence items should be reviewed by the LLM. That creates an intent/documentation mismatch between the skill's claimed behavior and the documented implementation approach.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring says the 'LLM reviews and adjusts categories before generating a report', which aligns with the manifest's promise of categorization 'with LLM reasoning'. However, the actual implementation only applies regex rules and simple fallback mappings, then emits a notice that some transactions 'need LLM review' without invoking any LLM or review mechanism.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The inline documentation explicitly describes a behavior that does not occur in the code. The implementation categorizes transactions via regex and bank-category mapping, then only prints informational messages about items needing review, so the documentation actively overstates the script's behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The comment says negative amounts are charges/debits and positive amounts are payments/credits, but the code classifies negative values as debits and then stores the absolute value separately. In a financial budgeting skill, incorrect sign/type semantics can silently misclassify spending versus income, leading downstream budget calculations, reports, or LLM-based categorization to produce materially wrong results.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code writes parsed bank and credit-card transactions to a JSON file, which is sensitive user financial data. Although the write is logged, there is no user-facing warning in the script description or around the output option that the operation creates a persistent file containing financial records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code writes categorized financial transaction data, including descriptions and amounts, to a user-specified file path. While the write is logged, there is no user-facing warning or comment noting that sensitive personal financial data will be persisted to disk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.