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

Content
View full analysis
/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"] = ``` 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
View remediation
/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
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 46)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 47)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 48)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 50)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 51)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/setup.sh (reported line 54)May include surrounding context.

sh
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

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · scripts/setup.sh (reported line 12)May include surrounding context.

sh
echo "💸 Invoice Chaser Setup"
echo "━━━━━━━━━━━━━━━━━━━━━━"

# Create config directory
mkdir -p "$CHASER_DIR"
mkdir -p "$CHASER_DIR/archives"
echo "✓ Created $CHASER_DIR"

Vague Triggers

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.