Back to skill

Security audit

etf-finance

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real ETF portfolio tracker, but its installer and local financial data handling need review before use.

Review the installer before running it. Prefer installing yfinance in a dedicated virtual environment with pinned versions, and restrict ~/.clawdbot/etf_investor permissions because positions and alerts can reveal private financial information. Expect the skill to create persistent local portfolio files and to delete them if you confirm uninstall.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
scripts/install.sh:24
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
/dev/null; then echo "" echo "Installing yfinance package..." pip3 install --user yfinance || pip3 install --break-system-packages yfinance fi ``` ### Technical Analysis The installation script retrieves the latest available `yfinance` package and its transitive dependencies without pinning versions or validating package hashes. Consequently, the dependency tree can change after the Skill has been reviewed. Python package installation can execute package build backends or setup logic. A compromised package release, compromised transitive dependency, or distribution-channel attack could therefore result in arbitrary code execution during installation. The fallback to `--break-system-packages` also bypasses Python's externally managed environment protection. Depending on the user's permissions and Python configuration, this may alter a shared or operating-system-managed Python environment rather than keeping the dependency isolated to the Skill. ### Attack Path 1. An attacker compromises a future `yfinance` release, one of its transitive dependencies, or the relevant package distribution channel. 2. A user runs `scripts/install.sh` when `yfinance` is not already importable. 3. The unversioned `pip3 install` command selects the compromised release. 4. Malicious installation or runtime code executes with the privileges of the user running the installer. 5. The malicious dependency can access resources available to that account, including the locally stored portfolio and alert files. ### Impact Assessment Successful exploitation provides code execution under the installing user's account. This may permit access to the user's files, portfolio records, network credentials available to the process, ...[truncated 239 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/install.sh:8
Finding

Portfolio and Alert Files Are Created Without Restrictive Permissions

Content
View full analysis
"$DATA_DIR/positions.json" echo "Created empty positions file: $DATA_DIR/positions.json" fi if [ ! -f "$DATA_DIR/alerts.json" ]; then echo "[]" > "$DATA_DIR/alerts.json" echo "Created empty alerts file: $DATA_DIR/alerts.json" fi ``` From `scripts/config.py`: ```python # Data directory DATA_DIR = os.path.expanduser("~/.clawdbot/etf_investor") # Positions file POSITIONS_FILE = os.path.join(DATA_DIR, "positions.json") # Alerts file ALERTS_FILE = os.path.join(DATA_DIR, "alerts.json") # Price cache file (optional, for storing latest prices) PRICES_FILE = os.path.join(DATA_DIR, "prices.json") # Ensure directory exists os.makedirs(DATA_DIR, exist_ok=True) ``` From `scripts/utils.py`: ```python def save_positions(positions): """Save positions to JSON file.""" with open(POSITIONS_FILE, 'w', encoding='utf-8') as f: json.dump(positions, f, indent=2, ensure_ascii=False) def load_alerts(): """Load alerts from JSON file.""" if not os.path.exists(ALERTS_FILE): return [] try: with open(ALERTS_FILE, 'r', encoding='utf-8') as f: return json.load(f) except (json.JSONDecodeError, IOError): return [] def save_alerts(alerts): """Save alerts to JSON file.""" with open(ALERTS_FILE, 'w', encoding='utf-8') as f: json.dump(alerts, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The data directory and JSON files are created without explicit access modes. Their effective permissions therefore d ...[truncated 1386 chars]
Remediation
View remediation
"$DATA_DIR/positions.json" printf '[]\n' > "$DATA_DIR/alerts.json" ``` 4. Correct permissions on existing installations: ```bash chmod 0700 "$DATA_DIR" chmod 0600 "$DATA_DIR/positions.json" "$DATA_DIR/alerts.json" ``` 5. In Python, create missing files with an explicit mode using `os.open`: ```python fd = os.open( POSITIONS_FILE, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600, ) with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(positions, f, indent=2, ensure_ascii=False) ``` 6. Use an owner-only temporary file and atomic replacement when saving JSON to reduce the chance of partial writes or unsafe file replacement. ]]>
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The declared description presents a full portfolio management skill with alerts, P/L tracking, and position management across specified finance data sources. The supplied code chunk only implements a basic command-line current-price lookup for a single symbol via an external utility function. While price retrieval could be a supporting part of the described skill, this chunk does not demonstrate most of the declared core capabilities, nor does it show the stated data-source usage. Therefore, the code behavior as provided is materially narrower than the declared purpose.

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 · README.md (reported line 20)May include surrounding context.

text

The install script will:
- Create the data directory at `~/.clawdbot/etf_investor/`
- Set up a Python virtual environment with yfinance
- Initialize empty positions and alerts files

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file includes an uninstall command and notes that it will remove all data files and configurations. Because the behavior affects user data, the skill description should present a clearer warning before or alongside the command so users understand the data-loss impact prior to running it.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documentation advertises commands that read and write local files, invoke shell scripts, and fetch remote market data, but it declares no explicit tool scope or permissions boundary. That makes the effective capability set opaque to users and reviewers, increasing the risk of overprivileged execution or unexpected file/network access if the skill is installed or extended.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation includes uninstall and delete operations but does not clearly warn that local portfolio and alert data may be removed or become unrecoverable. Users may run destructive commands expecting only software removal, causing unintended loss of financial tracking records and alert configuration.

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/install.sh (reported line 8)May include surrounding context.

sh
echo "Installing etf-investor skill..."

# Create the data directory
mkdir -p ~/.clawdbot/etf_investor

# Create empty files if they don't exist

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script is presented as a summary/view command, but when invoked with --update it fetches prices and persists changes to stored positions. This violates the principle of least surprise and can lead to unintended modification of local portfolio state, especially in automated workflows or when users expect a read-only reporting command.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The file presents core usage sections and safety-relevant instructions primarily in Chinese, while the skill name and top-level description are in English. This creates an implicit language constraint for users without documenting that the skill is Chinese-only or offering an English alternative, which can conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring says the script shows a portfolio summary, but the implementation also updates and saves positions. Misleading documentation around state-changing behavior can cause operators or higher-level agents to invoke the script in contexts where mutation is unsafe or unexpected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

Persisting updated prices without a visible warning means users may unknowingly alter portfolio records simply by requesting a refreshed summary. In an agent or scripting context, this can create auditability and integrity issues because local financial data changes as a side effect of reporting.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest identifies this skill as "etf-finance", but the script comments and user-facing messages describe uninstalling "etf-investor". This is an active documentation-to-code intent mismatch because the file appears to belong to one skill while its inline documentation and prompts claim it targets another.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code includes user-facing/docstring natural language and inline comments that hard-code a Chinese locale context (e.g. Tencent Finance and Chinese-language comments) for one execution path without documenting any user choice or region-specific requirement. Under the policy rule, forcing a specific language/locale without opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.