Back to skill

Security audit

Stock Watcher

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its stated stock-watchlist purpose and is scoped to its own local watchlist data, but users should notice that clear and uninstall actions can erase saved entries.

Install only if you are comfortable with a local watchlist file under ~/.clawdbot/stock_watcher and network lookups to 10jqka.com.cn. Back up the watchlist before using clear or uninstall, because those flows can erase saved entries without confirmation. Prefer installing Python dependencies in a virtual environment with pinned versions.

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
README.md:83
Finding
Unpinned Third-Party Python Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `README.md:83-87` **Vulnerability Type**: Unrestricted dependency installation **Risk Level**: Medium ### Vulnerable Code ```markdown ### "Command not found" errors Ensure you have Python 3 and required packages installed: ```bash pip3 install requests beautifulsoup4 ``` ``` The installation script repeats the unsafe recommendation at `scripts/install.sh:18-21`: ```bash if ! python3 -c "import requests, bs4" 2>/dev/null; then echo "Warning: Required Python packages (requests, beautifulsoup4) not found." echo "You may need to install them with: pip install requests beautifulsoup4" fi ``` ### Technical Analysis The project instructs users to install `requests` and `beautifulsoup4` without version constraints or integrity hashes. As a result, the installed dependency versions depend on the current state of the configured Python package index. Although both package names appear legitimate, the installation process does not guarantee that users receive versions reviewed by the project author. It is also affected by custom or compromised package indexes, dependency compromise, and malicious future releases. Python packages may execute arbitrary code during installation or when imported by the Skill. ### Attack Path 1. An attacker compromises a referenced package release, one of its transitive dependencies, or a package index configured on the victim's system. 2. The user follows the documented command: `pip3 install requests beautifulsoup4`. 3. Pip resolves and downloads an unreviewed package version from the configured index. 4. Malicious installation or import-time code executes under the account running pip or the Skill. 5. The malicious dependency can access resources available to that account and can alter the Skill's behavior. This path requires compromise or manipulation of the dependency supply chain; the audited project does not itself host or retrieve a known malicious package. ### ...[truncated 393 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a reviewed dependency lock or requirements file with exact versions: ```text requests==<reviewed-version> beautifulsoup4==<reviewed-version> ``` 2. Generate and verify cryptographic hashes, then install with: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Pin all transitive dependencies where reproducible builds are required. 4. Recommend installation inside a dedicated virtual environment rather than the system Python environment. 5. Periodically scan pinned dependencies for known vulnerabilities and update them through a controlled review process. 6. Update both `README.md` and `scripts/install.sh` so they reference the secured requirements file instead of unconstrained package names. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/add_stock.py:55
Finding
Missing Input Validation Permits Watchlist Record and Terminal-Control Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add_stock.py:55-84` **Vulnerability Type**: Improper input validation and unsafe line-oriented serialization **Risk Level**: Low ### Vulnerable Code ```python # Check if stock already exists stock_entry = f"{stock_code}|{stock_name}" stock_exists = False for existing in existing_stocks: if existing.startswith(f"{stock_code}|"): stock_exists = True break if stock_exists: print(f"Stock {stock_code} already in watchlist") return False # Add new stock existing_stocks.append(stock_entry) # Write back to file with proper newlines with open(WATCHLIST_FILE, 'w', encoding='utf-8') as f: for stock in existing_stocks: f.write(stock + '\n') print(f"Added stock {stock_code} ({stock_name}) to watchlist") return True if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python3 add_stock.py <stock_code> [stock_name]") sys.exit(1) stock_code = sys.argv[1] stock_name = sys.argv[2] if len(sys.argv) > 2 else None add_stock(stock_code, stock_name) ``` ### Technical Analysis The documentation states that stock codes are validated as six-digit numeric values, but `add_stock.py` passes command-line arguments directly to `add_stock()` without enforcing that constraint. It also writes the supplied stock name to a line-oriented file without rejecting newline characters, the `|` field delimiter, control characters, or oversized values. A supplied newline can create additional apparent watchlist records. A supplied delimiter can make records malformed. Terminal escape sequences are subsequently printed without sanitization by `list_stocks.py:27-33` and may also appear in output from `summarize_performance.py:78-94`. Arbitrary stock codes are also inserted into a fixed HTTPS URL by `add_stock.py:15` and `summarize_performance.py:18`. The hostname remains fixed, so this is not general server-side request forgery, but invalid values can ...[truncated 1351 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate stock codes before any file or network operation: ```python import re if not re.fullmatch(r"\d{6}", stock_code): raise ValueError("Stock code must contain exactly six digits") ``` 2. Reject names containing record delimiters, newlines, carriage returns, null bytes, or other control characters: ```python if "|" in stock_name or any(ord(ch) < 32 for ch in stock_name): raise ValueError("Stock name contains unsupported characters") ``` 3. Define a reasonable maximum stock-name length. 4. Replace the custom delimiter format with structured serialization such as JSON, while continuing to validate data after deserialization. 5. Escape or remove terminal control characters before printing stored values. 6. Apply the same validation when reading existing records so previously corrupted data is not trusted. 7. Write updates atomically through a securely created temporary file followed by `os.replace()` to reduce corruption from interrupted or concurrent writes. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill is presented as a stock watchlist manager, but the documentation also includes uninstall behavior that completely removes local files and describes destructive data-clearing operations outside the core user-facing purpose. Description-behavior mismatch is dangerous because users may invoke or install the skill expecting read-only or low-risk portfolio tracking while it also supports destructive local data removal that is not clearly framed in the main purpose statement.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README advertises a command that clears the entire watchlist without any visible warning about destructive behavior, confirmation requirements, or recoverability. In a stateful personal-data management skill, this can lead to accidental irreversible deletion of the user's tracked stocks through routine command use or copy-paste execution.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill documentation describes capabilities that require reading and writing local files and making network requests, but it does not declare any explicit tool scope or permissions. This is dangerous because it obscures the skill's effective authority from reviewers and users, reducing transparency and increasing the chance of over-privileged or unexpected actions being approved implicitly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill documents a 'clear watchlist' operation that fully erases user-maintained stock entries, but it does not mention any confirmation step, undo capability, or warning about irreversible data loss. This creates a realistic risk of accidental or socially engineered deletion of user data through a simple prompt.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The uninstall instructions state that running the uninstall script will completely remove all related files, but there is no warning that user watchlist data may be deleted as part of that process. This is dangerous because users may treat uninstall as routine cleanup without realizing it can irreversibly destroy their saved portfolio tracking data.

Session Persistence

Medium
Category
Rogue Agent
Content
echo "Installing stock-watcher skill dependencies..."

# Create the watchlist directory
mkdir -p ~/.clawdbot/stock_watcher

# Create empty watchlist file if it doesn't exist
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.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The user-facing output strings on these lines are fixed in Chinese, which imposes a specific language/locale on all users. The file does not provide any opt-in, configuration, or documented justification for this locale constraint.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The uninstall section presents the uninstall command before clearly emphasizing that it removes both the skill and user watchlist data, which increases the chance of accidental destructive execution. While the text later mentions data removal, the warning is not prominent enough for a destructive operation that may permanently erase user data.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The document switches into Chinese for key usage instructions and examples, but it does not indicate that language selection is optional or based on user preference. This can violate language/locale policy when a specific language is effectively imposed without opt-in.

Static analysis

No suspicious patterns detected.