Back to skill

Security audit

Agent Ledger

Security checks for vulnerabilities and agentic risk

Overview

This is a local earnings ledger, but its financial-record handling is under-hardened and its description overstates supported payment features.

Review before installing if you would use this for real payments or client records. It does not appear to exfiltrate data or install persistence beyond local files, but it stores financial metadata and wallet information in plaintext and has input-validation flaws that could corrupt or misrepresent ledger data. Treat it as a simple local tracker, not a reliable invoicing or payment accounting system.

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/ledger.sh:80
Finding

Unvalidated line selector permits sed program injection

Content
View full analysis
}" if [[ ! -f "$LEDGER_FILE" ]]; then echo "No entries."; exit 1; fi sed -i '' "${LINE}s/\"pending\"/\"paid\"/" "$LEDGER_FILE" echo "💚 Marked line $LINE as paid." ;; ``` ### Technical Analysis The `pay` command expects `LINE` to be a positive ledger line number, but it does not validate the value before embedding it into a sed program. Shell quoting prevents ordinary shell metacharacter expansion, but it does not prevent sed-language injection because the entire attacker-controlled value is interpreted as part of the sed script. An attacker can supply sed commands, command separators, ranges, or embedded newline characters instead of a numeric line selector. This allows operations beyond changing the requested entry from `pending` to `paid`. For example, the following argument introduces an additional substitution: ```bash bash scripts/ledger.sh pay \ '1s/"amount":[0-9.]*/"amount":999999/;2' ``` The resulting sed program is effectively: ```sed 1s/"amount":[0-9.]*/"amount":999999/;2s/"pending"/"paid"/ ``` This changes the amount in the first record and marks the second record as paid. Implementations supporting sed's `w` command can also be made to copy ledger content to an attacker-selected local file. Embedded newlines can terminate the injected command and preserve a syntactically valid final substitution. The exact available commands and syntax depend on the installed sed implementation. The use of `sed -i ''` is also specific to BSD-style sed and is not portable to common GNU sed invocations, but that compatibility problem does not mitigate the injection weakness. ### Attack Path 1. An attacker or untrusted automation component gains the ability to choose the argument passed to `ledger.sh pay`. 2. In ...[truncated 1114 chars]
Remediation
View remediation
}" if [[ ! "$LINE" =~ ^[1-9][0-9]*$ ]]; then echo "Error: line number must be a positive integer." >&2 exit 1 fi TOTAL_LINES=$(wc -l < "$LEDGER_FILE") if (( LINE > TOTAL_LINES )); then echo "Error: ledger line does not exist." >&2 exit 1 fi ``` Prefer replacing the sed-based update with structured JSON processing using `jq`. Write the result to a securely created temporary file in the same directory, check that processing succeeded, and then atomically rename it over the ledger: ```bash tmp=$(mktemp "$LEDGER_DIR/ledger.jsonl.XXXXXX") trap 'rm -f "$tmp"' EXIT jq -c --argjson target "$LINE" ' if input_line_number == $target and .status == "pending" then .status = "paid" else . end ' "$LEDGER_FILE" > "$tmp" mv -- "$tmp" "$LEDGER_FILE" trap - EXIT ``` The exact jq filter should be tested against JSON Lines input. Also reject attempts to pay an entry whose current status is not `pending`, and report whether a record was actually updated. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ledger.sh:28
Finding

Unescaped task data enables JSON corruption, CSV formula injection, and terminal control-sequence injection

Content
View full analysis
> "$LEDGER_FILE" echo "✅ Added: $DESC — \$$AMOUNT ($STATUS)" ;; ``` The stored fields are later extracted with regular expressions and printed directly to a terminal: ```bash while IFS= read -r line; do local_n=$((local_n + 1)) DATE=$(echo "$line" | sed 's/.*"date":"\([^"]*\)".*/\1/' | cut -c1-10) TASK=$(echo "$line" | sed 's/.*"task":"\([^"]*\)".*/\1/') AMT=$(echo "$line" | sed 's/.*"amount":\([0-9.]*\).*/\1/') STATUS=$(echo "$line" | sed 's/.*"status":"\([^"]*\)".*/\1/') ICON=$([[ "$STATUS" == "paid" ]] && echo "💚" || echo "🟡") if [[ -z "$FILTER" ]] || [[ "$STATUS" == "$FILTER" ]]; then printf " %s %-3s %-12s %-38s \$%s\n" "$ICON" "$local_n." "$DATE" "$TASK" "$AMT" fi done < "$LEDGER_FILE" ``` CSV output also interpolates the values without correct escaping or spreadsheet-formula neutralization: ```bash echo "date,task,amount,status" while IFS= read -r line; do DATE=$(echo "$line" | sed 's/.*"date":"\([^"]*\)".*/\1/') TASK=$(echo "$line" | sed 's/.*"task":"\([^"]*\)".*/\1/') AMT=$(echo "$line" | sed 's/.*"amount":\([0-9.]*\).*/\1/') STATUS=$(echo "$line" | sed 's/.*"status":"\([^"]*\)".*/\1/') echo "\"$DATE\",\"$TASK\",$AMT,\"$STATUS\"" done < "$LEDGER_FILE" ``` ### Technical Analysis `DESC`, `AMOUNT`, and `STATUS` are accepted without appropriate validation. Directly embedding the ...[truncated 2987 chars]
Remediation
View remediation
&2 exit 1 fi case "$STATUS" in pending|paid) ;; *) echo "Error: status must be pending or paid." >&2 exit 1 ;; esac jq -cn \ --arg id "$ID" \ --arg date "$DATE" \ --arg task "$DESC" \ --argjson amount "$AMOUNT" \ --arg status "$STATUS" \ '{id:$id, date:$date, task:$task, amount:$amount, status:$status}' \ >> "$LEDGER_FILE" ``` Additional hardening should include: 1. Parse every ledger entry with `jq` rather than sed so escaped strings and field ordering are handled correctly. 2. Reject invalid JSON records and fail safely rather than silently calculating from malformed content. 3. Implement RFC 4180 CSV escaping by doubling embedded double quotes and consistently quoting every field. 4. If CSV files are intended for spreadsheet applications, neutralize values beginning with `=`, `+`, `-`, or `@`, for example by prefixing a single quote, and document that behavior. 5. Remove or visibly escape terminal control characters before displaying untrusted descriptions. 6. Consider imposing reasonable length limits on descriptions and wallet values. 7. Add tests covering quotes, backslashes, newlines, Unicode, formula-leading characters, malformed amounts, unsupported statuses, and terminal escape sequences. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill’s documentation materially overstates its capabilities by claiming invoice generation and crypto/fiat asset tracking that are not evidenced in the described commands or data model. This can mislead downstream agents or users into relying on the skill for financial recordkeeping and payment workflows it does not actually support, creating integrity and trust risks around billing, balances, and payment status.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README explicitly states that wallet addresses and earnings records are stored under a predictable local path, but it does not warn users that this information may be sensitive financial metadata. While this is not an active exploit by itself, it can lead to unintentional exposure through backups, shared machines, logs, or permissive filesystem settings, especially for agents handling real payments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This shell script creates a persistent directory in the user's home folder and writes both ledger entries and wallet configuration there. Although the file operations are visible in code comments and echoed for some commands, there is no explicit user disclosure that running the tool will create and retain local financial/task data on disk.

Content

No source excerpt is available for this finding.