Back to skill

Security audit

StockBuddy

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent stock and portfolio assistant, but it needs review because it can silently erase saved portfolio positions during migration and its installer can modify the Python environment.

Review this skill before installing. It stores portfolio and account facts locally, calls external market/news/filing services, and can produce action-oriented trading guidance. Do not run the dependency installer in a system Python environment unless you accept the package-management risk, and back up any existing ~/.stockbuddy/stockbuddy.db before use because the migration code can erase legacy positions.

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

T08 · Insecure Dependencies

Warning
Location
scripts/install_deps.sh:15
Finding

Unpinned Dependencies Can Modify the System Python Environment

Content
View full analysis

Vulnerability Details

File Location: scripts/install_deps.sh, lines 15-24
Vulnerability Type: Unpinned third-party dependencies and unsafe system package modification
Risk Level: Medium

Vulnerable Code

bash
# Try installation, including a PEP 668 bypass
pip3 install numpy pandas --quiet 2>/dev/null
if [ $? -ne 0 ]; then
    echo "Trying installation with --break-system-packages..."
    pip3 install --break-system-packages numpy pandas --quiet 2>/dev/null
fi

if [ $? -ne 0 ]; then
    echo "Trying a user-level installation..."
    pip3 install --user numpy pandas --quiet 2>/dev/null
fi

Technical Analysis

The installer resolves mutable package names without pinning reviewed versions or validating package hashes. It also relies on the invoking environment's pip configuration, including any configured package index or extra index.

The --break-system-packages fallback bypasses the protections applied to externally managed Python environments under PEP 668. Consequently, the script may overwrite or introduce incompatible packages in a shared Python installation rather than isolating project dependencies.

This is a supply-chain and environment-integrity weakness. It is not evidence that the currently named packages are malicious, but it leaves installation behavior dependent on mutable external artifacts and local pip configuration.

Attack Path

  1. The required modules are absent, causing the documented dependency installer to run.
  2. The script invokes pip with unpinned package names.
  3. Pip resolves packages through the indexes configured in the execution environment.
  4. A compromised index, mirror, DNS path, or maliciously altered pip configuration supplies an unexpected distribution.
  5. Package build or installation code executes with the privileges of the user running the installer.
  6. If the ordinary installation fails, --break-system-packages permits modification of the externally managed Python environment.

I

...[truncated 620 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create and use a dedicated virtual environment rather than modifying the system interpreter.
  2. Pin reviewed dependency versions in a lock file or requirements file.
  3. Require hashes, for example through pip install --require-hashes -r requirements.txt.
  4. Explicitly use a trusted HTTPS package index and review any configured extra indexes.
  5. Remove the --break-system-packages fallback.
  6. Prefer binary wheels from trusted sources where practical, reducing exposure to arbitrary package build steps.
  7. Keep installation failures visible instead of suppressing all diagnostic output with 2>/dev/null.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze_stock.py:153
Finding

Primary Market Quotes Are Retrieved over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_stock.py, lines 153-164
Vulnerability Type: Unauthenticated and unencrypted external market-data retrieval
Risk Level: Medium

Vulnerable Code

python
def fetch_tencent_quote(code: str) -> dict:
    """Retrieve a real-time Tencent Finance quote."""
    stock = normalize_stock_code(code)
    symbol = stock['tencent_symbol']
    url = f"http://qt.gtimg.cn/q={symbol}"

    for attempt in range(MAX_RETRIES):
        try:
            req = urllib.request.Request(url, headers={
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'Referer': 'https://gu.qq.com/',
            })
            with urllib.request.urlopen(req, timeout=10) as response:

Technical Analysis

The primary quote endpoint uses HTTP rather than HTTPS. HTTP provides neither transport confidentiality nor server authentication and does not protect response integrity.

The response is parsed as authoritative market data. Its price, valuation, market-capitalization, and related fields flow into portfolio valuation, profit-and-loss calculations, technical analysis, and trading recommendations. There is no cryptographic verification or independent consistency check before those values are used.

Although the ticker symbol is constrained by stock-code normalization and this is not a general server-side request forgery primitive, an on-path attacker can still observe requested symbols and alter provider responses.

Attack Path

  1. A user requests analysis of a stock or portfolio.
  2. The script sends a plaintext HTTP request containing the normalized ticker.
  3. An attacker controlling or observing the network path intercepts the connection.
  4. The attacker returns or modifies a syntactically valid Tencent quote response.
  5. _parse_tencent_quote accepts the manipulated fields.
  6. The altered data is persisted in the local watchlist metadata and used to calculate ...[truncated 585 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace the endpoint with an authenticated HTTPS equivalent.
  2. If that provider cannot offer HTTPS, disable it as the primary source and use an HTTPS provider instead.
  3. Cross-check security-sensitive quote fields against an independent HTTPS source before producing actionable recommendations.
  4. Reject structurally inconsistent responses and apply sanity checks to price, percentage-change, timestamp, and valuation fields.
  5. Record source and validation status in the output, and mark recommendations as non-execution-ready when quote integrity cannot be established.
  6. Avoid persisting quote data obtained over an unauthenticated transport unless it has been independently validated.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/db.py:49
Finding

Legacy Schema Migration Silently Deletes All Portfolio Positions

Content
View full analysis

Vulnerability Details

File Location: scripts/db.py, lines 49-53
Vulnerability Type: Destructive and non-recoverable database migration
Risk Level: High

Vulnerable Code

python
def _migrate_schema(conn: sqlite3.Connection) -> None:
    positions_cols = _table_columns(conn, "positions")
    if positions_cols and "watchlist_id" not in positions_cols:
        conn.execute("DROP TABLE positions")
        positions_cols = []

    if positions_cols:

Technical Analysis

When an existing positions table does not contain watchlist_id, the migration drops the entire table. It does not back up the database, rename and preserve the legacy table, transform old rows, verify migration results, or request user confirmation.

Normal commands repeatedly call init_db(), which invokes this migration. Therefore, merely running the application against a legacy database can trigger irreversible loss of durable portfolio state.

This is a destructive migration flaw rather than an external privilege-escalation vulnerability. Exploitation requires a database with the legacy schema or the ability to alter that local database's schema.

Attack Path

  1. A user has an existing ~/.stockbuddy/stockbuddy.db whose positions table predates the watchlist_id column.
  2. The user runs an ordinary portfolio or analysis command.
  3. The command calls init_db().
  4. _migrate_schema discovers that the table exists without watchlist_id.
  5. The code executes DROP TABLE positions.
  6. The current initialization transaction creates or retains an empty replacement schema.
  7. Existing position records are lost without an automatic recovery path.

If another local process already has permission to modify the database, it could also recreate the triggering legacy schema so that the next normal invocation deletes the positions table. That does not extend the attacker's operating-system privileges, but it can make destructive modification occur through the app ...[truncated 525 chars]

Remediation
View remediation

Remediation Suggestions

  1. Back up the database before applying any schema migration.
  2. Run the complete migration inside an explicit transaction.
  3. Rename the legacy table rather than dropping it immediately.
  4. Create the new schema and transform each legacy record into the new watchlist and positions representation.
  5. Verify row counts, required fields, and foreign-key integrity before committing.
  6. Roll back on any transformation or verification failure.
  7. Keep the renamed legacy table or backup until migration success is confirmed.
  8. Store and check an explicit schema version so migrations are deterministic and sequential.
  9. Add automated migration tests using representative databases from every supported prior release.
  10. Require explicit user confirmation when a safe automatic migration is impossible.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill presents itself as a stock-analysis assistant, but also includes environment-modifying package installation behavior via pip. Hidden or under-disclosed package-management actions are risky because they alter the runtime, may execute arbitrary install-time code from dependencies, and expand the attack surface beyond the user’s expected task.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill presents itself as a stock-analysis assistant, but also includes environment-modifying package installation behavior via pip. Hidden or under-disclosed package-management actions are risky because they alter the runtime, may execute arbitrary install-time code from dependencies, and expand the attack surface beyond the user’s expected task.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 207)May include surrounding context.

md
| `scripts/analyze_stock.py` | Core analysis script for market data retrieval, technical indicators, and valuation scoring |

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The migration logic unconditionally drops the entire positions table when it detects a missing watchlist_id column, which destroys all stored portfolio positions. In a portfolio/trading assistant, positions are core user data, so this can erase holdings history and account associations during startup or upgrade without user consent or recovery.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code performs a destructive schema change silently, with no disclosure, confirmation, backup, or rollback path. Because the skill manages positions, cash, and trading context, silent deletion of the positions table can directly undermine the integrity of portfolio analysis and execution-aware recommendations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill describes behaviors that require network access and persistent file/database writes, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an overbroad execution surface where a host agent may grant more capability than users or reviewers expect, reducing least-privilege protections and making misuse of network/file actions harder to govern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The description says to use the skill for broad requests like 'stock analysis', 'portfolio analysis', 'buy/sell advice', and 'practical trading actions' for a stock code or company name. These are common conversational intents and the file does not provide negative examples or clearer scope constraints, which increases the chance of unintended invocation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill explicitly persists durable financial facts such as positions, account context, cash balances, and trading constraints in a local SQLite database under the user home directory. Persistent storage of sensitive portfolio/account data increases privacy and data-retention risk, especially if retention limits, access controls, encryption, or user consent/visibility are not clearly defined.

Content

Scanner excerpt · SKILL.md (reported line 15)May include surrounding context.

md
**Core rule: separate durable facts from derived values.**
- **Persist durable facts**: share count, cost basis, account, available cash, market/currency, lot size, odd-lot support, and other user-confirmed trading constraints
- **Compute in real time**: latest price, market value, position weight, unrealized P&L, executable buy/sell size, and whether partial selling is actually possible
- Do **not** write latest price, position weight, or unrealized P&L back into durable storage

Five core scenarios:
1. **Single-stock analysis** — analyze one stock and produce an action recommendation

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file mandates a default Chinese response format without checking the user's language preference. This can cause responses in an unexpected language, increasing the risk of user misunderstanding—especially for financial recommendations, order prices, and risk disclosures where clarity is important.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The template explicitly treats vague phrases like “分析一下”, “给我建议”, and “今天怎么操作” as triggers for stock analysis. In a broadly routed assistant, these generic utterances overlap with everyday speech and can cause unintended invocation of a trading skill, leading to unsolicited financial analysis or action-oriented output in the wrong context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The entire reference is written in Chinese and does not indicate that the user can choose another language or that the skill is intentionally limited to Chinese-speaking users. The policy calls for flagging language or locale constraints when they are imposed without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring states this is a Hong Kong stock analysis script using Tencent Finance for technical and fundamental analysis. In practice, the code supports CN/HK/US markets and fetches data from multiple additional external services, including Eastmoney fallback for A-shares, Yahoo for US K-line data, Google News RSS, and SEC filings. This is a substantive expansion beyond the documented behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The top-level docstring, usage examples, and most user-facing strings in this code are written only in Chinese, which effectively fixes the skill's interface to a specific language. The file does not offer any user opt-in, locale selection, or explanation that this is intentionally limited to a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/analyze_stock.py (reported line 693)May include surrounding context.

python
if not cik:
            return {'source': 'sec', 'items': []}
        req = urllib.request.Request(
            f'https://data.sec.gov/submissions/CIK{cik}.json',
            headers={'User-Agent': 'Mozilla/5.0 stockbuddy@example.com'}
        )
        with urllib.request.urlopen(req, timeout=20) as response:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script automatically modifies the Python environment and escalates to pip3 install --break-system-packages if normal installation fails, which can overwrite or conflict with OS-managed Python packages. This is dangerous because it makes system-impacting changes without explicit informed consent, and in an agent skill context such a script may be invoked as part of setup by users who do not understand the risks to their workstation or server environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring, usage instructions, and command descriptions are presented only in Chinese, with no indication that language can be selected by the user. This creates a locale/language constraint in the skill's natural-language interface without an explicit opt-in or documented justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The analyze command can persist detailed portfolio analysis, including positions, account balances, and profit/loss data, to an arbitrary file path. Although the CLI exposes an --output option, the code provides no cautionary comment, confirmation, or user-facing warning that sensitive financial data will be written to disk and may overwrite existing content.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

Examples like 'can I buy this stock' and 'look at BYD' are broad natural phrases that could occur in casual conversation. The section provides examples but no boundaries for when the skill should not activate, so trigger scope remains underspecified.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

Phrases like 'look at my holdings' and similar examples in later scenario sections are ordinary portfolio conversation and may overlap with general chat. Because the document does not state exclusion conditions or a stricter invocation context, activation remains potentially overbroad.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The comment labels the following section as 'technical indicator calculation (unchanged)'. However, the subsequent codebase includes not only indicator functions but also expanded composite scoring, market regime detection, confidence estimation, backtesting, and buy/sell recommendation generation, which goes beyond a 'unchanged indicators' section. This creates misleading documentation about what the section actually contains.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

All user-facing comments and console output are in Chinese, with no indication that the language is configurable or chosen by the user. Under the policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.