Back to skill

Security audit

Invoice Chaser

Security checks for vulnerabilities and agentic risk

Overview

This skill is clearly for invoice follow-up automation, but it handles business payment records and potential outbound collection emails with incomplete shipped controls and a real local data-corruption bug.

Review carefully before installing. This skill is not evidence of theft or malware, but it is intended for sensitive business workflows and recurring client outreach. Do not enable scheduled sending until the missing chase/status/report scripts and safety controls are available and reviewed, and avoid untrusted invoice numbers until the jq injection bug is fixed.

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/add-invoice.sh:92
Finding
jq Program Injection Through an Unescaped Invoice Number<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add-invoice.sh`, lines 92 and 148 **Vulnerability Type**: User-controlled jq program injection **Risk Level**: Medium ### Vulnerable Code ```bash # Check if invoice number already exists if jq -e ".invoices[\"$INV_NUMBER\"]" "$INVOICES_FILE" > /dev/null; then echo "Error: Invoice number '$INV_NUMBER' already exists." exit 1 fi # ... # --- SAVE TO FILE --- temp_file=$(mktemp) jq ".invoices[\"$INV_NUMBER\"] = $invoice_json" "$INVOICES_FILE" > "$temp_file" && mv "$temp_file" "$INVOICES_FILE" ``` ### Technical Analysis The `INV_NUMBER` value is obtained from the user-controlled `--number` command-line argument and interpolated directly into two jq programs. Quoting the shell variable prevents shell word splitting, but it does not make the value safe for inclusion in jq source code. An invoice number containing a quote, closing bracket, and jq operators can terminate the intended property lookup and inject additional jq expressions. The first vulnerable invocation is used for duplicate detection, while the second transforms the database and writes the result back to `invoices.json`. For example, an invoice number shaped like: ```text x"] = {} | .invoices["attacker ``` changes the duplicate-check filter into an expression equivalent to: ```jq .invoices["x"] = {} | .invoices["attacker"] ``` and changes the database update into an expression equivalent to: ```jq .invoices["x"] = {} | .invoices["attacker"] = <new invoice object> ``` This can bypass the intended unique-key behavior and modify records other than the literal invoice number supplied by the caller. More generally, arbitrary jq filters can be introduced, allowing an attacker to delete, replace, or restructure data in the invoice database. This is jq-language injection rather than direct shell command injection. The demonstrated code does not provide operating-system command execution, because the injected content is interpreted ...[truncated 1895 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never construct jq source code by directly interpolating user-controlled values. Pass the invoice number as a jq string argument and the invoice object as a JSON argument: ```bash # Safe duplicate check if jq -e --arg number "$INV_NUMBER" '.invoices[$number]' \ "$INVOICES_FILE" > /dev/null; then echo "Error: Invoice number '$INV_NUMBER' already exists." exit 1 fi # Safe database update temp_file=$(mktemp) if jq \ --arg number "$INV_NUMBER" \ --argjson invoice "$invoice_json" \ '.invoices[$number] = $invoice' \ "$INVOICES_FILE" > "$temp_file"; then mv -- "$temp_file" "$INVOICES_FILE" else rm -f -- "$temp_file" echo "Error: Failed to update invoice database." >&2 exit 1 fi ``` Apply additional defense-in-depth validation to invoice numbers. If business requirements permit, restrict them to a documented allowlist such as letters, digits, periods, underscores, and hyphens: ```bash if [[ ! "$INV_NUMBER" =~ ^[A-Za-z0-9._-]{1,100}$ ]]; then echo "Error: Invalid invoice number format." >&2 exit 1 fi ``` Additional hardening should include: 1. Validate that the existing database has the expected object structure before updating it. 2. Validate all numeric and date inputs before creating the invoice object. 3. Remove the temporary file through a cleanup trap if the script exits before `mv`. 4. Add regression tests using invoice numbers containing quotes, brackets, pipes, backslashes, and jq operators. 5. Consider file locking around the read-check-write sequence to prevent concurrent invocations from losing updates. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Run `scripts/setup.sh` to initialize config and data directories
2. Edit `~/.config/invoice-chaser/config.json` with email templates, timing, and escalation rules
3. Ensure `gog` skill is installed (for Gmail sending)
4. Set `GOG_DEFAULT_ACCOUNT` in `~/.clawdbot/secrets.env` (e.g., `your-email@gmail.com`)
5. Test with: `scripts/add-invoice.sh --test`

## Config
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The skill's 'use when' description is broad enough to activate in routine accounting, invoicing, status, or reporting contexts without clearly signaling that it can send real outbound payment-chasing emails. That raises the risk of unintended invocation and autonomous contact with external client addresses, which can cause financial, reputational, and privacy harm even without malicious code.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The chase-cycle documentation describes loading invoices, determining stages, and sending reminder emails on schedule, but it does not prominently warn that normal operation can send real emails to customer billing contacts. In an automation context, insufficient warning increases the chance a user triggers live collections-style outreach unintentionally, potentially damaging client relationships and exposing business data.

Session Persistence

Medium
Category
Rogue Agent
Content
echo "💸 Invoice Chaser Setup"
echo "━━━━━━━━━━━━━━━━━━━━━━"

# Create config directory
mkdir -p "$CHASER_DIR"
mkdir -p "$CHASER_DIR/archives"
echo "✓ Created $CHASER_DIR"
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Vague Triggers

Low
Confidence
86% confidence
Finding
This JSON manifest defines multiple automated reminder stages using generic fields like "trigger_days" and "trigger_from", but it does not specify exclusion conditions, negative examples, or additional scope constraints for when a stage should or should not activate. In a manifest file, this can lead to unintended activations or overlap between stages because the activation semantics are underspecified.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The manifest fixes business-hour behavior to "America/New_York", which imposes a specific locale on all scheduling behavior. Under the language/locale policy, hard-coded locale constraints should either be user-selectable or clearly justified as region-specific.

Static analysis

No suspicious patterns detected.