Back to skill

Security audit

Watch My Money

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but its local-only financial report has under-disclosed privacy and HTML-safety risks that need review before installation.

Review this skill before installing. It handles private financial data and saves reports locally, which is disclosed, but the generated report can contact Google Fonts despite the no-network claim and the template does not define safe escaping for merchant or transaction text. Use only with trusted input or after fixing the template to remove external resources, add a restrictive content policy, and require HTML escaping for all generated report values.

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

other

Warning
Location
assets/template.html:394
Finding

External Google Fonts Request Violates the Local-Only Privacy Guarantee

Content
View full analysis
Remediation
View remediation
``` 4. Test generated reports while monitoring network activity and verify that opening a report produces no DNS, HTTP, or HTTPS requests. 5. If external resources intentionally remain, remove the “No network calls” claim and clearly disclose the destination and metadata exposure before report generation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
assets/template.html:443
Finding

Unescaped Raw HTML Report Placeholders Enable Stored HTML or Script Injection

Content
View full analysis
{{ALERTS_HTML}} ``` ```html
{{CATEGORIES_HTML}}
``` ```html {{MERCHANTS_HTML}} ``` ### Technical Analysis Transaction descriptions and derived merchant names originate from user-supplied CSV files or pasted transaction text. These values are therefore untrusted input. The Skill directs the report generator to construct and inject complete HTML fragments, but it does not require contextual HTML encoding, sanitization, or safe DOM construction. If a transaction description or merchant name contains HTML, such as an image element with an event handler, direct string interpolation can cause that markup to become executable report content. This creates a stored injection condition: the malicious value is first stored in transaction or report data and then activated when the generated HTML file is opened. An illustrative malicious transaction description is: ```text ``` Whether arbitrary script execution occurs in practice depends on the omitted report generator's interpolation behavior. No generator implementation is included in the project, so the audit cannot verify that these values are escaped elsewhere. The documented generation procedure and template do not establish a safe encoding boundary. ### Attack Path 1. An attacker supplies a crafted bank-export file, shared transaction list, or transactio ...[truncated 1374 chars]
Remediation
View remediation
`, `"`, and `'`. 3. Do not build report sections by concatenating untrusted values into HTML strings. Prefer DOM creation and assign values through `textContent`. 4. If raw fragment generation is unavoidable, construct markup only from fixed, trusted templates and sanitize the final fragment with a maintained allowlist-based HTML sanitizer. 5. Prohibit event-handler attributes, scripts, iframes, embedded objects, unsafe URLs, and attacker-controlled style attributes. 6. Validate numeric fields separately and constrain CSS progress widths to numeric values within an expected range. 7. Add a restrictive Content Security Policy. Move the existing inline script to a local JavaScript file or authorize it with a per-report nonce rather than broadly allowing inline execution. 8. Add regression tests using malicious merchant descriptions, including: ```text "><svg onload=alert(1)> ``` 9. Verify that these payloads are displayed as literal text and never create executable DOM elements. 10. Document the required output-encoding rules directly in `SKILL.md` so that any Agent implementing the described workflow applies the same security boundary. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (10)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/template.html (reported line 398)May include surrounding context.

html
</style>
</head>
<body>
    <!-- HEADER CARD -->
    <div class="header-card">
        <p class="scope">{{TRANSACTION_COUNT}} transactions · {{CURRENCY}}</p>
        <h1 class="month-title">{{MONTH_DISPLAY}}</h1>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/template.html (reported line 427)May include surrounding context.

html
<button class="control-btn" onclick="expandAll()">Expand All</button>
    </div>
    
    <!-- ALERTS SECTION -->
    <div class="alerts-section {{ALERTS_EMPTY_CLASS}}" id="alerts-section">
        <div class="section-header" onclick="this.parentElement.classList.toggle('collapsed')">
            <span class="section-title">⚠️ Alerts</span>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/template.html (reported line 469)May include surrounding context.

html
</div>
            </div>
            -->
            <!-- TEMPLATE: Category Card without Budget
            <div class="category-card">
                <div class="category-header">
                    <span class="category-name">Category Name</span>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/template.html (reported line 482)May include surrounding context.

html
</div>
    </div>
    
    <!-- TOP MERCHANTS SECTION -->
    <div class="section" id="merchants-section">
        <div class="section-header" onclick="this.parentElement.classList.toggle('collapsed')">
            <span class="section-title">🏪 Top Merchants</span>

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger list is very broad and matches common, natural-language budgeting requests, increasing the chance the skill activates when a user did not explicitly intend to invoke this specific tool. Because the skill processes sensitive financial data and writes persistent local state and reports, unintended activation can expose or retain private transaction information without clear user intent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

The skill generates and persists HTML and JSON reports plus state files containing transaction history, merchant data, budgets, and spending patterns under the user's home directory. Even though storage is local-only, this is still sensitive financial information retained across sessions, which increases exposure if the device, account, or files are accessed by another local user, backup system, or unrelated tooling.

Content

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

md
### 6. Generate HTML Report

Create local HTML file with:
- Month summary (income, expenses, net)
- Category breakdown with budget status
- Top merchants

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented reset-state command is destructive, but the skill description and surrounding guidance do not prominently warn that it can erase budgets, merchant overrides, and history. A user or calling agent could invoke it without understanding the data-loss consequence, leading to irreversible loss of financial tracking state.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The template imports Google Fonts from an external domain, which causes the user's browser to make a network request when rendering a local financial report. In the context of a bank transaction analysis skill, this leaks metadata such as IP address, user agent, timing, and report access to a third party, undermining the expectation of a local/private workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The copySummary function copies sensitive financial summary data to the system clipboard without any warning, confirmation, or indication of downstream exposure risk. Clipboard contents may be read by other applications, pasted into the wrong destination, or persist beyond the user's intent, which is especially sensitive for banking and budget data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The HTML root sets lang="en", which fixes the document language to English with no indication of user selection or locale configurability. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is documented and justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.