Back to skill

Security audit

stock-prediction-daily

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent A-share stock prediction skill with disclosed local files, market-data access, and a local dashboard, but users should treat saved model files as trusted executable artifacts.

Install only if you are comfortable with a finance workflow that fetches market data, writes cached data/models/results under the skill directory, and may start a localhost dashboard. Do not load copied or downloaded .pkl/.joblib model files unless you trust their source; retrain locally or verify artifacts first. Treat the port-5000 troubleshooting command as unsafe unless you first identify the process and know it belongs to this dashboard.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/predict.py:36
Finding
Unsafe Deserialization of Local Model Artifacts## Vulnerability Details **File Location**: `scripts/predict.py:36-41` **Vulnerability Type**: Unsafe pickle-compatible deserialization **Risk Level**: Medium ### Vulnerable Code ```python def load_model(): model = joblib.load(config.MODEL_PATH) with open(config.FEATURE_PATH) as f: feature_names = json.load(f) scaler = joblib.load(config.SCALER_PATH) return model, feature_names, scaler ``` The affected artifact paths are defined in `scripts/config.py:45-47`: ```python MODEL_PATH = os.path.join(MODEL_DIR, "xgb_stock_model.pkl") FEATURE_PATH = os.path.join(MODEL_DIR, "feature_names.json") SCALER_PATH = os.path.join(MODEL_DIR, "scaler.pkl") ``` ### Technical Analysis `joblib.load()` relies on Python's pickle-compatible deserialization mechanism. Pickle artifacts can contain object-reconstruction instructions that invoke arbitrary Python callables during loading. Therefore, loading an attacker-controlled `.pkl` file is equivalent to executing untrusted code. The model and scaler are normally generated locally by `scripts/train.py`, so this finding does not indicate intentionally embedded malicious behavior. However, `load_model()` performs no signature, checksum, ownership, permission, symlink, or provenance validation before deserializing the files. A replaced artifact in a shared, compromised, or attacker-writable project directory could consequently execute code when prediction starts. ### Attack Path 1. An attacker gains the ability to replace either `scripts/models/xgb_stock_model.pkl` or `scripts/models/scaler.pkl`, such as through a compromised project archive, shared writable workspace, poisoned artifact distribution, or another process with write access. 2. The attacker creates a malicious pickle-compatible artifact whose reconstruction routine executes an operating-system command or arbitrary Python code. 3. A user runs `python3 predict.py`, or runs `python3 main.py` with th ...[truncated 1181 chars]
Remediation
## Remediation Suggestions 1. **Replace executable serialization formats** - Store the XGBoost model using a non-pickle model format, such as JSON or UBJSON. - Store scaler parameters and feature metadata in validated JSON or another non-executable data format. - Reconstruct the scaler from validated numeric fields rather than deserializing a Python object. 2. **Authenticate artifacts** - Generate a cryptographic digest or digital signature when training completes. - Verify the digest or signature before loading either artifact. - Store the trusted verification key or expected digest separately from the writable artifact directory. 3. **Restrict filesystem access** - Place model artifacts in a directory writable only by the owning user. - Reject symbolic links and files with unexpected ownership or group/world-writable permissions. - Open and validate artifacts using race-resistant filesystem operations where supported. 4. **Validate artifact provenance and schema** - Record model version, expected type, library versions, feature count, and training metadata. - Reject artifacts with unexpected metadata or incompatible versions. - Do not accept downloaded or user-supplied `.pkl` files unless they originate from an authenticated source. 5. **Document the trust boundary** - Clearly warn that `joblib` and pickle artifacts must never be loaded from untrusted sources. - Treat models bundled in third-party archives or copied from shared locations as executable content. 6. **Use containment as defense in depth** - Run prediction under a dedicated, least-privileged account or isolated container. - Limit filesystem access, environment secrets, and outbound network access available to the prediction process.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents the skill as an end-to-end stock prediction system with seven major capabilities, including model training, feature optimization, prediction generation, evaluation, Flask dashboard output, and direct invocation of sector/stock analysis skills. The supplied code implements only the web app/dashboard and report-rendering portion. It reads precomputed prediction/evaluation/report files from disk, formats markdown-like reports into HTML, builds summary cards/charts from saved report contents, and serves five Flask routes (/predictions, /report, /evaluation, /sector-analysis, /stock-analysis). There is no XGBoost training, no cross-validation execution, no model file output, no feature engineering/selection pipeline execution, no Tencent market data fetching, and no direct calls to stock-sector-research or stock-watchlist-briefing—only display of report files that may have been produced elsewhere. While the dashboard and evaluation display align partially with the declared purpose, the primary declared scope is much broader than this code chunk’s actual behavior, so this chunk materially under-implements and misrepresents several declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code chunk is narrowly focused on preprocessing: generating technical-analysis features and a binary target label from OHLCV data. This can be a supporting component of a stock prediction system, but it does not itself perform the majority of the declared system capabilities. There is no XGBoost training, no cross-validation, no model persistence, no optimization or feature selection orchestration, no prediction workflow, no evaluation logic, no Flask app/dashboard, and no calls to sector-analysis or watchlist-analysis skills. Therefore the declared description materially overstates what this code chunk actually does.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill describes file read/write operations, network access to external market-data APIs, and cross-skill delegation, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where an agent may grant broader capabilities than intended, increasing the risk of unintended file access, external requests, or delegated actions.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger language for multiple capabilities is broad enough that ordinary finance-related requests could invoke expensive or side-effecting actions such as model training, network data collection, file generation, or launching a web app. In an agent setting, overbroad invocation criteria can cause unintended execution and expand exposure to external systems and local file writes without clear user intent.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The optimization trigger includes generic phrases like improving accuracy or poor model performance, which could match casual discussion and unintentionally kick off retraining or parameter changes. Because optimization can modify artifacts and consume compute while relying on external data and cached files, accidental activation has meaningful operational and security consequences.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The sector-analysis trigger scope is broad and delegates execution to another skill, which compounds risk because a loosely matched request can transitively invoke additional tools, network access, or file writes outside the user's precise intent. Delegation increases uncertainty about downstream behavior, making broad trigger criteria more dangerous in context.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The individual-stock-analysis trigger can overlap with ordinary stock discussion and may cause automatic delegation to another skill plus file output. Because this skill also mixes local report persistence with external-data-oriented analysis, ambiguous triggering can result in unrequested data gathering, delegation, and artifact creation.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The troubleshooting guide recommends `lsof -ti:5000 | xargs kill -9`, which forcefully terminates whatever processes are using port 5000 without any confirmation, process inspection, or warning. In an agent skill context, users may copy-paste this directly, causing unintended termination of unrelated local services or data loss from abrupt process death.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file contains hardcoded Chinese field names, page titles, UI labels, and user-facing messages throughout the app, such as stock field headers and route titles. This imposes a single language experience without offering user opt-in, selection, or a clearly documented region-specific justification in the file.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The function docstring explicitly states it returns Chinese names, and the metadata throughout the file hard-codes Chinese feature names and categories. This imposes a specific language/locale on downstream consumers without offering a language choice or documenting a justified region-specific requirement.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest frames this skill as an A-share daily (日线) prediction system, but the declared feature metadata includes hour/minute and cyclical encodings for intraday timestamps. Those features are not an obvious implementation detail of daily prediction and expand the behavior beyond the stated daily scope.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The implementation extracts hour and minute from datetime/date columns and generates cyclical encodings, which indicates support for intraday temporal modeling. For a manifest that specifically advertises daily stock rise/fall prediction, this is a semantic mismatch rather than a necessary implementation detail.

Insecure deserialization: joblib.load()

Medium
Category
Dangerous Code Execution
Content
def load_model():
    model = joblib.load(config.MODEL_PATH)
    with open(config.FEATURE_PATH) as f:
        feature_names = json.load(f)
    scaler = joblib.load(config.SCALER_PATH)
Confidence
93% confidence
Finding
joblib.load() deserializes Python pickle-compatible content and can execute arbitrary code during loading if the model file is tampered with. In this skill, the path comes from configuration and the loaded object is trusted implicitly, so any compromise of the model artifact supply chain, local storage, or deployment packaging could lead to code execution in the agent environment.

Insecure deserialization: joblib.load()

Medium
Category
Dangerous Code Execution
Content
model = joblib.load(config.MODEL_PATH)
    with open(config.FEATURE_PATH) as f:
        feature_names = json.load(f)
    scaler = joblib.load(config.SCALER_PATH)
    return model, feature_names, scaler
Confidence
93% confidence
Finding
Loading the scaler with joblib.load() has the same unsafe deserialization risk as loading the model: a crafted .joblib file can trigger arbitrary code execution at load time. Because this script runs as part of an automated prediction pipeline, exploitation could occur before any prediction logic executes.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The HTML root sets `lang="zh-CN"`, which hard-codes a specific language/locale for the interface. Under the policy, this is a natural-language locale restriction unless the skill offers user opt-in or clearly documents a justified region-specific constraint, which is not evident in this file.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This HTML template contains user-facing labels and descriptions entirely in Chinese, such as section headings and explanatory text. Forcing a specific language without user opt-in can violate language/locale policy when the skill is not clearly documented as region-specific.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This HTML template hard-codes user-facing headings, descriptions, and labels in Chinese throughout the report, such as at L017-L018, L037-L038, and L192-L193. Forcing a specific language in user-visible content without opt-in or justification matches the natural-language locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This HTML template presents multiple user-facing labels in Chinese, such as creation time, file, sections, and tables, and the pattern continues throughout the page. Because the skill forces a specific language in natural-language output without any visible opt-in or justification that the skill is China-specific, it matches the language/locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The generated report embeds Chinese-language strings for the project background, feature categories, and usage guide. This imposes a specific language/locale in user-facing output without any opt-in, configurability, or justification that the skill is intended only for Chinese-speaking users.

Vague Triggers

Low
Confidence
84% confidence
Finding
L180 的“展示结果”或“搭建仪表盘”缺乏上下文约束,可能覆盖很多非本技能场景下的常见表达。对于触发描述,文件未提供明确排除条件或限定必须基于本技能产物。

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The entire reference document is presented only in Chinese, including headings, configuration descriptions, and stock-pool details, with no indication that the skill supports user language choice. Under the policy rule, forcing a specific language without opt-in can be a natural-language policy violation unless the locale restriction is clearly documented and justified.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The troubleshooting content uses Chinese throughout and does not state that the skill supports multiple languages or that Chinese is a region-specific requirement. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The configuration uses Chinese stock codes and Chinese company names exclusively, which embeds a specific locale/language assumption into the skill. Under the policy, forcing a specific language or locale without user opt-in can be a natural-language policy concern when no alternative locale choice or justification is provided in the file.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The file-level docstring and schema use Chinese-only field names and the runtime prints multiple Chinese messages, which effectively constrains the skill to a single language/locale. The policy allows locale constraints only when they are explicitly documented and justified or when the user is given a choice, neither of which appears here.

Missing User Warnings

Low
Confidence
78% confidence
Finding
This code persists prediction history and per-run snapshots to disk via `to_csv`, which is a file-write operation covered by the warning requirement for code files. While the script prints save locations after the write completes, there is no prior disclosure in comments/docstrings or confirmation that running the skill will append to and create files in the configured paths.

Static analysis

No suspicious patterns detected.