Back to skill

Security audit

Invoice Forge

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local invoice tool, but it needs Review because generated invoices can include unescaped active HTML and custom invoice numbers can write files outside the intended output folder.

Review before installing or using with untrusted client data. Treat generated HTML invoices as active browser content until escaping is fixed, avoid custom invoice numbers from untrusted sources, run tests only in an isolated folder, and do not expose the data directory through cloud sync, SSH, or a server without separate access controls and backups.

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)

T09 · Insecure Skill Coding Practices

Error
Location
invoice_template.py:99
Finding

Stored HTML and Script Injection in Generated Invoices

Content
View full analysis
{desc} {qty} {fmt(rate)} {fmt(amount)} """ ``` The completed HTML document also directly interpolates other values without escaping: ```python
{logo_html}

{business['name']}

{business['address'].replace(chr(10), '
')}

{business['email']}

{business['phone']}

{f"

{business['website']}

" if business['website'] else ""}

INVOICE

Invoice #: {invoice_number}

Date: {invoice_date}

Due Date: {due_date}

{status_text}
``` ```python

Bill To

{client.get('name', '')}

{client.get('email', '')}

{f"

{client.get('address', '').replace(chr(10), '
')}

" if client.get('address') else ""} {f"

{client.get('phone', '')}

" if client.get('phone') else ""}
``` ```python {f'''

Payment Details

text
{payment_details}
''' if payment_details else ''} {f'
Notes: {notes}
' if notes else ''} {f'
Terms: {terms}
' if terms else ''} ...[truncated 2711 chars]
Remediation
View remediation
str: return escape(str(value), quote=True) ``` Use this helper for invoice numbers, descriptions, client fields, business fields, notes, terms, payment details, tax labels, discount information, and statuses. 2. Preserve intended line breaks only after escaping: ```python safe_address = html_text(address).replace("\n", "
") ``` Do not replace newlines before escaping, because that would also escape the intentionally inserted `
` elements. 3. Validate website and link values separately. Permit only explicitly supported schemes, such as `https`, rather than treating arbitrary configuration values as safe markup. 4. Prefer a maintained template engine with automatic HTML escaping if adding a dependency is acceptable. Keep automatic escaping enabled and use explicit safe-markup annotations only for internally generated markup. 5. Consider adding a restrictive Content Security Policy to generated HTML, for example one that blocks scripts and limits external resources. This is defense in depth and does not replace proper output encoding. 6. Add regression tests using payloads containing: ```text "> & < > " ' ``` The tests should verify that these values appear as encoded text and do not create executable elements or attributes. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
invoice_forge.py:351
Finding

Path Traversal and File Overwrite Through Unsanitized Invoice Numbers

Content
View full analysis
Dict: ``` ```python if invoice_number is None: invoice_number = self._generate_invoice_number() ``` ### Technical Analysis `save_rendered_invoice()` treats `invoice_data["invoice_number"]` as a filename component without validating it. `os.path.join()` does not prevent traversal when the filename contains `../` segments, and it does not guarantee that the normalized destination remains under `self.output_dir`. For example, with an output directory of `output`, an invoice number of: ```text ../../target ``` produces: ```text output/../../target.html ``` The operating system resolves the parent-directory segments when opening the path, allowing the write to escape the configured invoice directory. If the destination already exists and backups a ...[truncated 2298 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 1)May include surrounding context.

md
---
name: "Invoice Forge Professional Invoice Generator"
description: "Professional invoice generation for freelancers and small businesses. Generate beautiful invoices in seconds. No dependencies, no subscriptions, no cloud required. Clean Python code."
author: "@TheShadowRose"

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

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

Content

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

md
---
name: "Invoice Forge Professional Invoice Generator"
description: "Professional invoice generation for freelancers and small businesses. Generate beautiful invoices in seconds. No dependencies, no subscriptions, no cloud required. Clean Python code."
author: "@TheShadowRose"

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · LIMITATIONS.md (reported line 322)May include surrounding context.

md
The limitations above are **design choices**, not bugs:
- No database = no migrations, no corruption
- No cloud = no downtime, no data breaches
- No auth = no password resets, no account recovery
- No framework = no bloat, no security patches

If you need more features, fork it! The code is MIT-licensed and easy to extend.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This test script performs non-trivial persistent state changes: it adds a client, creates invoices, updates invoice status, and writes output/data files, yet it gives no warning, isolation, or cleanup. Running it against a real or shared environment can pollute business records, overwrite assumptions in later runs, or cause users to mistake test artifacts for legitimate data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The documentation recommends Dropbox/Google Drive sync, SSH access, and server deployment as workarounds without clearly warning about the security implications of exposing invoice data to third-party storage or remote access paths. Users may adopt these suggestions without implementing encryption, access restrictions, or authentication, increasing the risk of data exposure or unauthorized access.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The philosophy section states 'No auth' as a defining property, but elsewhere the document explicitly suggests SSH for remote access and mentions adding your own authentication when running on a server. That creates an intent-level contradiction in the documentation about whether authentication is absent as part of the system model or merely not built into the tool itself.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The configuration examples set CURRENCY_SYMBOL = "$" and CURRENCY_CODE = "USD" as defaults, which nudges users toward a specific locale/currency without any explicit opt-in or note that these are only examples. Under the policy, locale-specific defaults should either offer a user choice or be clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · README.md (reported line 588)May include surrounding context.

md
**USE AT YOUR OWN RISK.**

- The author(s) are NOT liable for any damages, losses, or consequences arising from 
  the use or misuse of this software — including but not limited to financial loss, 
  data loss, security breaches, business interruption, or any indirect/consequential damages.
- This software does NOT constitute financial, legal, trading, or professional advice.
- Users are solely responsible for evaluating whether this software is suitable for

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

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

md
**USE AT YOUR OWN RISK.**

- The author(s) are NOT liable for any damages, losses, or consequences arising from 
  the use or misuse of this software — including but not limited to financial loss, 
  data loss, security breaches, business interruption, or any indirect/consequential damages.
- This software does NOT constitute financial, legal, trading, or professional advice.
- Users are solely responsible for evaluating whether this software is suitable for

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The generated HTML hard-codes the document language as English, which is a natural-language locale choice applied to all rendered invoices. The file does not offer a way for callers to select another locale or document why English is required, so this conflicts with the policy against forcing a language without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.