Back to skill

Security audit

Fund Invest Advisor

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a local fund-analysis helper, but it ships an under-documented portfolio script with verified command-injection and data-integrity risks.

Review before installing. The main fund.sh calculator is local and purpose-aligned, but the package includes script.sh with local code-execution and portfolio-data integrity flaws. Avoid running script.sh, especially with untrusted arguments or FUND_DIR values, until it is fixed; treat all investment outputs as educational, not personalized financial advice.

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:64
Finding

Python Code Injection Through an Attacker-Controlled Portfolio Path

Content
View full analysis
"; return; } python3 << PYEOF import json holdings = {} with open('$PORTFOLIO') as f: ``` ### Technical Analysis The `FUND_DIR` environment variable influences `PORTFOLIO`. The resulting path is interpolated directly into an unquoted heredoc that is interpreted as Python source code. Although the path appears inside a single-quoted Python string, Bash performs parameter expansion before Python receives the heredoc. A path containing a single quote and additional Python syntax can terminate the string literal and inject arbitrary statements or expressions. Shell quoting of `"$PORTFOLIO"` elsewhere does not protect this operation because the vulnerability occurs when Bash constructs the embedded Python program. The same vulnerable `cmd_holdings` implementation is also reached through the `pnl` command. ### Attack Path 1. An attacker causes the victim to run the script with an attacker-controlled `FUND_DIR` value. 2. The attacker chooses a value containing Python string delimiters and executable Python syntax. 3. The script creates or uses the resulting directory and derives `PORTFOLIO` from it. 4. The victim invokes: - `scripts/script.sh holdings`, or - `scripts/script.sh pnl`. 5. Bash expands `$PORTFOLIO` into the unquoted Python heredoc. 6. The injected path terminates the intended Python string and introduces attacker-controlled Python code. 7. Python executes that code with the privileges and environment of the user running the script. ### Impact Assessment Succes ...[truncated 462 chars]
Remediation
View remediation
" return fi python3 - "$PORTFOLIO" <<'PYEOF' import json import sys portfolio_path = sys.argv[1] holdings = {} with open(portfolio_path, encoding="utf-8") as f: for line in f: d = json.loads(line) fund = d["fund"] amount = float(d["amount"]) if d["action"] == "buy": holdings[fund] = holdings.get(fund, 0) + amount else: holdings[fund] = holdings.get(fund, 0) - amount PYEOF } ``` Additional hardening should include: - Use quoted heredoc delimiters whenever the embedded source must remain literal. - Validate that `FUND_DIR` resolves to an expected user-owned location. - Reject unsafe directory types, including symbolic links where inappropriate. - Create the data directory with restrictive permissions, such as `umask 077` and `mkdir -p -- "$DATA_DIR"`. - Add regression tests using paths containing quotes, backslashes, spaces, newlines, and Python metacharacters. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:170
Finding

Shell Command Execution Through Unvalidated Arithmetic Expressions

Content
View full analysis
}" local months="${2:-12}" local total=$((amount * months)) ``` ### Technical Analysis The `amount` and `months` command-line arguments are accepted as arbitrary strings and then referenced as variables inside Bash arithmetic expansion. Bash arithmetic evaluation is not equivalent to parsing a strictly numeric value. Variable values can be recursively interpreted as arithmetic expressions. Crafted expressions involving array subscripts or command substitutions can cause shell commands to be evaluated while Bash resolves the arithmetic expression. Because neither input is checked against a strict numeric grammar before `$((amount * months))` is evaluated, attacker-controlled command-line data reaches an execution-capable shell context. The later Python conversions do not mitigate this issue because the vulnerable arithmetic expansion occurs first. ### Attack Path 1. An attacker supplies or persuades a victim to use a crafted `amount` or `months` argument. 2. The victim invokes the `dca` command, for example through `scripts/script.sh dca ...`. 3. `cmd_dca` stores the untrusted strings without validation. 4. Bash evaluates `local total=$((amount * months))`. 5. During recursive arithmetic evaluation, attacker-supplied shell constructs are evaluated. 6. Any resulting command executes with the privileges of the user running the script. ### Impact Assessment Successful exploitation can result in arbitrary command execution as the invoking user. This permits access to user-readable files, modification or deletion of portfolio and other user data, execution of local programs, and use of inherited credentials or network permissions. No independent privilege-escalation mechan ...[truncated 176 chars]
Remediation
View remediation
}" local months="${2:-12}" if [[ ! "$amount" =~ ^[0-9]+$ ]] || [[ ! "$months" =~ ^[0-9]+$ ]]; then echo "Amount and months must be non-negative integers." >&2 return 2 fi local total=$((10#$amount * 10#$months)) # Continue with the calculation. } ``` The `10#` prefix prevents leading-zero values from being treated as octal. Further hardening should include: - Define reasonable upper limits to prevent integer overflow or resource-exhaustion behavior. - If decimal amounts are required, avoid Bash arithmetic and parse the arguments with Python or another numeric parser. - Pass numeric strings through positional arguments or environment variables only after validation. - Add negative tests containing arithmetic operators, variable references, brackets, command substitutions, whitespace, signs, and excessively large values. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:46
Finding

Portfolio JSONL Injection Through Unsafe Transaction Serialization

Content
View full analysis
[date]}" local amount="${2:?}" local date="${3:-$(date +%Y-%m-%d)}" printf '{"action":"buy","fund":"%s","amount":%s,"date":"%s"}\n' "$fund" "$amount" "$date" >> "$PORTFOLIO" echo "[fund] Bought: $fund ¥$amount on $date" _log "buy" "$fund ¥$amount" } cmd_sell() { local fund="${1:?Usage: fund-invest-advisor sell [date]}" local amount="${2:?}" local date="${3:-$(date +%Y-%m-%d)}" printf '{"action":"sell","fund":"%s","amount":%s,"date":"%s"}\n' "$fund" "$amount" "$date" >> "$PORTFOLIO" ``` ### Technical Analysis The script manually constructs JSON with `printf` rather than using a JSON serializer: - `fund` and `date` are inserted into quoted JSON strings without escaping quotes, backslashes, control characters, or newlines. - `amount` is inserted as an unquoted JSON token without validation that it is a finite numeric value. - Each generated object is appended to a JSON Lines file, so an embedded newline can create additional attacker-controlled records. A malicious input can therefore corrupt the persistent portfolio file, inject forged transactions, or create content that causes later `json.loads` operations to fail. This affects `holdings`, `pnl`, `history`, and export-related behavior that relies on the same file. ### Attack Path 1. An attacker supplies a crafted fund name, date, or amount to the `add` or `sell` command. 2. The crafted value contains JSON delimiters, escape characters, a newline, or a nonnumeric raw token. 3. `printf` appends the value without JSON encoding or validation. 4. The persistent `portfolio.jsonl` file becomes malformed or contains additional forged transaction records. 5. Subs ...[truncated 728 chars]
Remediation
View remediation
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 (11)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger text is broad and loosely scoped to generic fund-investment decisions, which can cause the skill to activate in many financial-advice contexts without clear user intent. In a financial domain, accidental invocation is more sensitive because the skill may influence investment choices, asset allocation, and risk-taking based on simplified local calculations and generic heuristics.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Nearly all user-facing strings, help text, and instructions are presented only in Chinese, with no opt-in, alternative language support, or explicit statement that the skill is intentionally limited to a Chinese-speaking or region-specific audience. This creates a natural-language locale policy issue because the skill effectively imposes a specific language on all users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script provides concrete investment allocation, strategy, risk, and FIRE guidance with prescriptive recommendations but does not present a clear financial-risk disclaimer or state that outputs are educational only. In a skill context, users may over-trust the advice as personalized or reliable, which can lead to real financial harm from unsuitable decisions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The help text documents pnl as a distinct "Profit & loss summary" capability, which implies reporting gains/losses rather than current position totals. In the command dispatcher, pnl simply invokes cmd_holdings, producing holdings output and not any profit/loss calculation, so the documented intent contradicts the actual behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file contains only Chinese-language content from title to footer, with no opt-in, alternative language option, or statement that the skill is intended specifically for a Chinese-speaking audience. Under the policy rule for language/locale constraints, forcing a single language without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The help text documents only a subset of implemented commands, while additional commands such as sharpe, maxdd, kelly, monte, fire, var, irr, and cost are callable. This capability mismatch can mislead users, reviewers, or policy controls about what the skill can do, reducing transparency and making oversight weaker even though the hidden commands here are not directly dangerous.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text describes rebalance <target-file> as providing rebalance suggestions, implying a working advisory feature. In reality, the dispatcher only echoes TODO: rebalance, so the inline documentation overstates what the code does.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help output lists screen <criteria> as a fund screening feature. The corresponding command path only prints TODO: screening, which directly conflicts with the documented availability of that functionality.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text lists calendar as a dividend/rebalance calendar feature, suggesting an operational command. The actual handler only prints TODO: calendar, so the documented intent does not match the code behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text presents import <file> under Data commands as an available feature for importing holdings. However, the dispatcher for import only prints TODO: import, meaning the documentation claims a capability the code does not actually provide.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.