Back to skill

Security audit

Ledger

Security checks for vulnerabilities and agentic risk

Overview

This skill is a simple local ledger logger, but it overstates its finance capabilities and contains unsafe shell handling that can execute commands if config inputs are attacker-controlled.

Install only if you want a basic local text log, not real financial analysis or reporting. Do not pass untrusted config keys or values, do not store secrets in its config, review permissions on ~/.ledger, and treat exported CSV files as sensitive before opening them in spreadsheet software.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:145
Finding

Command Injection Through Dynamically Constructed GNU sed Program

Content
View full analysis
/dev/null; then sed -i "s|^${key}=.*|${key}=${val}|" "$cfg" ``` ### Technical Analysis The `key` and `val` command-line arguments are embedded directly into a GNU `sed` program. Neither argument is validated or escaped for use in a regular expression, replacement expression, or `sed` command. An attacker can inject the `sed` delimiter and the GNU-specific `e` flag. The `e` flag executes the resulting pattern space through a shell. By first creating a configuration key containing a shell command and then updating that key with a value that terminates the replacement expression, an attacker can cause arbitrary shell commands to run. The use of shell quoting around the overall `sed` argument does not prevent this vulnerability because the injection occurs in the language interpreted by `sed`, rather than through initial shell word splitting. ### Attack Path 1. The attacker must be able to invoke the Skill and control the arguments supplied to the `config` command. 2. The attacker creates a configuration key whose text is also a valid shell command, with a comment marker preventing the remainder from affecting execution: ```bash scripts/script.sh config 'touch /tmp/ledger-pwned #' seed ``` 3. This creates the following configuration entry: ```text touch /tmp/ledger-pwned #=seed ``` 4. The attacker updates the same key with a value that closes the replacement field, enables GNU `sed` execution, and comments out the final delimiter: ```bash scripts/script.sh config 'touch /tmp/ledger-pwned #' 'x|e;#' ``` 5. The dynamically generated `sed` expression replaces the matching line with text beginning with: ```text touch /tmp/ledger-pwned #=x ``` 6. GNU `sed` processes the injected `e ...[truncated 772 chars]
Remediation
View remediation
&2 return 1 fi ``` 2. Replace the dynamic `sed` expression with a parser that treats the key and value strictly as data. A temporary file can be generated with `awk`, followed by an atomic rename. 3. If `awk` is used, pass values through `-v` rather than concatenating them into program source. 4. Reject or safely encode newline characters in configuration values. 5. Write the replacement file in the same directory, apply mode `600`, and atomically rename it over the original. 6. Add regression tests using `sed` delimiters, regular-expression metacharacters, semicolons, newlines, and GNU `sed` flags in both key and value arguments. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:8
Finding

Financial Data Files Are Created Without Restrictive Permissions

Content
View full analysis
> "$DATA_DIR/data.jsonl" } ``` Configuration data is similarly appended without setting a restrictive file mode: ```bash echo "${key}=${val}" >> "$cfg" ``` ### Technical Analysis The Skill handles financial ledger records but does not set a restrictive `umask` or explicitly enforce permissions on its data directory and files. The effective permissions therefore depend on the environment of the caller. Under a commonly used `umask` of `022`, `mkdir -p` can create the ledger directory with mode `755`, while shell redirection can create `data.jsonl` and `config.txt` with mode `644`. This permits other local users to traverse the directory and read the files. The problem also applies when `LEDGER_DIR` points to a newly created location. Existing directories or files with insecure permissions are not detected or corrected. ### Attack Path 1. The Skill is run on a multi-user system under a permissive `umask`, such as `022`. 2. The user adds a financial entry: ```bash umask 022 scripts/script.sh add 'Confidential payment information' ``` 3. The directory and data file may be created with permissions equivalent to: ```text drwxr-xr-x ~/.ledger -rw-r--r-- ~/.ledger/data.jsonl ``` 4. Another local account can traverse the directory and read the ledger file if parent-directory permissions permit it. 5. Configuration values written to `config.txt` may be exposed in the same way. ### Impact Assessment The vulnerability can disclose ledger entries and configuration values to other local users. ...[truncated 377 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:12
Finding

Improper JSON and CSV Escaping Enables Data Corruption and Spreadsheet Formula Injection

Content
View full analysis
> "$DATA_DIR/data.jsonl" } ``` CSV fields are exported without quoting or formula neutralization: ```bash csv) echo "timestamp,command,value" > "$out" while IFS= read -r line; do ts=$(echo "$line" | grep -o '"ts":"[^"]*' | cut -d'"' -f4) c2=$(echo "$line" | grep -o '"cmd":"[^"]*' | cut -d'"' -f4) vl=$(echo "$line" | grep -o '"val":"[^"]*' | cut -d'"' -f4) echo "$ts,$c2,$vl" >> "$out" done < "$DATA_DIR/data.jsonl" ;; ``` ### Technical Analysis The `_save_entry` function constructs JSON manually with `printf`. User-controlled entry values are not escaped for quotation marks, backslashes, carriage returns, newlines, or other JSON control characters. A malicious or malformed entry can therefore terminate the `val` string, inject additional fields, or introduce extra physical lines into the JSONL file. The export logic compounds this issue by parsing JSON using `grep` and `cut`, which are not JSON parsers and cannot correctly process escaped strings or structurally malformed records. For CSV exports, values are concatenated with commas without RFC 4180 quoting. Commas, quotation marks, and newlines can create extra cells or rows. In addition, values beginning with spreadsheet formula markers such as `=`, `+`, `-`, or `@` may be interpreted as formulas when a user opens the export in spreadsheet software. ### Attack Path #### JSONL corruption 1. An attacker or untrusted data source supplies an entry containing a quotation mark or newline: ```bash scripts/scri ...[truncated 1740 chars]
Remediation
View remediation
> "$DATA_DIR/data.jsonl" ``` 3. Validate every existing JSONL record before listing, searching, removing, or exporting it. 4. Generate CSV using a library or encoder implementing RFC 4180 quoting. At minimum, wrap fields in double quotes and double every embedded quotation mark. 5. If exports may be opened in spreadsheet software, neutralize cells beginning with `=`, `+`, `-`, or `@`, such as by prefixing an apostrophe, and document this transformation. 6. Preserve embedded newlines safely rather than allowing them to create unintended CSV rows. 7. Add tests covering quotation marks, commas, backslashes, Unicode, carriage returns, newlines, and spreadsheet formula prefixes. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill markets itself as performing ledger calculations, investment analysis, and financial reporting, but the documented behavior only exposes generic CRUD-style storage operations. This kind of description-behavior mismatch can mislead users or an invoking agent into trusting the skill with finance-sensitive tasks it does not actually implement, causing incorrect outputs, unsafe automation decisions, or inappropriate handling of financial data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The invocation text is very broad and covers common finance workflows such as expenses, investments, and reporting, which increases the chance an agent will select this skill for sensitive or high-trust tasks. In context, that is risky because the rest of the skill documentation does not substantiate those capabilities, so overbroad routing language may drive misuse and unreliable financial task execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The markdown advertises removal and export operations without clearly warning that they modify local data and write files, which can lead an agent or user to trigger destructive or privacy-impacting actions unexpectedly. In a finance-themed skill, silent deletion or export is more sensitive because entries may contain financial records or business data that should not be removed or written out without explicit consent and destination review.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest and help text describe a finance-oriented analytics skill for tracking expenses, analyzing investments, or generating reports. However, the code does not perform ledger calculations, investment analysis, or report generation; it simply stores arbitrary text entries in a JSONL file and provides basic CRUD/search/export operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The config command writes arbitrary key/value pairs directly to a plaintext file in the user's home directory without warning, masking, or access-control hardening. In a financial-data context, users may store API keys, account identifiers, or other sensitive settings, which can then be exposed to other local users, backups, or malware reading the filesystem.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.