Back to skill

Security audit

Market Oracle

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its financial news and market-analysis purpose, but its article URL feature can fetch arbitrary locations and may leak fetched text into external news searches.

Review before installing. This skill is not malicious on the artifacts inspected, but it should only be used if you are comfortable granting live network access to Google News, Yahoo Finance, Finviz, and yfinance, and you should avoid passing private, local, internal, or authenticated URLs to `--url`. Prefer explicit event text or public HTTPS news links, and install dependencies in an isolated 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)

T09 · Insecure Skill Coding Practices

Error
Location
tools/event_analyze.py:43
Finding
Unrestricted URL Fetching Enables SSRF and Local File Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `tools/event_analyze.py:43-57` and `tools/event_analyze.py:2169-2193` **Vulnerability Type**: Server-Side Request Forgery and local resource disclosure **Risk Level**: High ### Vulnerable Code ```python def extract_text_from_url(url, timeout=15): """Extract main text content from a URL.""" req = urllib.request.Request(url, headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/131.0.0.0 Safari/537.36' }) try: with urllib.request.urlopen(req, timeout=timeout) as resp: html = resp.read().decode('utf-8', errors='replace') extractor = HTMLTextExtractor() extractor.feed(html) text = extractor.get_text() # Truncate to reasonable length return text[:3000] if len(text) > 3000 else text except Exception as e: return f"[无法提取URL内容: {e}]" ``` The URL is supplied directly through a command-line argument: ```python event_text = args.event or '' if args.url: print(f"📥 提取URL内容: {args.url}", file=sys.stderr) url_content = extract_text_from_url(args.url) if event_text: event_text = event_text + '\n\n原文摘要:\n' + url_content else: event_text = url_content if not event_text: print("ERROR: 请提供 --event 或 --url 参数", file=sys.stderr) sys.exit(1) ``` Retrieved content is also used to construct an external news query: ```python news_data = None if not args.skip_news: print("📰 获取事件相关新闻...", file=sys.stderr) search_terms = event_text[:50] news_data = run_tool('news_fetch.py', ['--query', search_terms, '--limit', '8']) ``` ### Technical Analysis The `--url` value is passed directly to `urllib.request.urlopen()` without validating its scheme, hostname, resolved IP address, port, or redirect destination. Consequently, the fetcher is not limited to public HTTPS news pages ...[truncated 2604 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit only explicitly approved schemes, preferably `https`. 2. Reject `file://`, `ftp://`, `data:`, and all other non-HTTPS schemes. 3. Parse URLs with `urllib.parse.urlsplit()` and reject: - Embedded credentials. - Empty or malformed hostnames. - Unexpected ports. - Hostnames such as `localhost`. 4. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, and reserved ranges. 5. Explicitly block common cloud metadata destinations, including link-local metadata addresses. 6. Disable automatic redirects or validate the scheme, hostname, port, and resolved address again after every redirect. 7. Prevent DNS rebinding by connecting only to an address that was validated and ensuring the connection does not resolve the hostname independently to a different address. 8. Enforce a response byte limit while streaming instead of reading the complete response before truncation. 9. Restrict accepted content types to expected textual or HTML media types. 10. Do not automatically use fetched document content as an external search query. Construct queries from separately validated user-supplied keywords or require explicit consent. 11. Run network-fetching functionality in a sandbox with restricted filesystem access and an outbound network allowlist. 12. Return generic errors to callers and log detailed network errors only to a protected diagnostic channel. ]]>

T08 · Insecure Dependencies

Warning
Location
tools/requirements.txt:1
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `tools/requirements.txt:1` and `setup.sh:19-22` **Vulnerability Type**: Non-reproducible and insufficiently constrained dependency installation **Risk Level**: Medium ### Vulnerable Code The dependency uses an open-ended minimum version: ```text yfinance>=0.2.36 ``` The setup script installs the dependency directly: ```bash if [ -f "$TOOLS_DIR/requirements.txt" ]; then echo "📦 Installing Python packages..." python3 -m pip install -r "$TOOLS_DIR/requirements.txt" --quiet echo "✅ Dependencies installed." else echo "⚠️ requirements.txt not found, skipping pip install." fi ``` ### Technical Analysis The version constraint `yfinance>=0.2.36` permits pip to install any current or future release satisfying the lower bound. Transitive dependencies are likewise resolved dynamically. No lock file, package hashes, or exact reviewed versions are provided. This makes installation non-reproducible and allows the effective dependency set to change after the skill package has been audited. A future compromised release, compromised transitive dependency, or incompatible update could introduce arbitrary installation-time or import-time behavior. The setup script also installs into whichever Python environment is selected by `python3`. It does not create or require an isolated virtual environment, increasing the chance of modifying a shared user or system environment. No evidence was found that the current `yfinance` package is malicious. The confirmed issue is the unsafe dependency policy and mutable installation result. ### Attack Path 1. A user runs `setup.sh`. 2. The script invokes pip using the open-ended requirements specification. 3. Pip resolves the latest matching `yfinance` release and its current transitive dependencies. 4. If a future matching package release or dependency has been compromised, pip downloads and installs that code. 5. Package installation hooks or later imports execute ...[truncated 879 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the open-ended lower bound with an exact reviewed version. 2. Generate a lock file that pins all transitive dependencies. 3. Require package hashes, for example by using a hash-locked requirements file with pip's `--require-hashes` option. 4. Install dependencies inside a dedicated virtual environment rather than the invoking user's shared Python environment. 5. Use a trusted package index explicitly and disable unneeded supplemental indexes to reduce dependency-confusion exposure. 6. Review dependency updates before changing the lock file. 7. Add automated vulnerability and package-integrity scanning to the release process. 8. Document that setup should not be run as root or with unnecessary administrative privileges. 9. Consider separating dependency installation from normal skill execution so that runtime invocation never silently modifies the Python environment. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code’s actual functionality is limited to retrieving and formatting market price data from Yahoo Finance for predefined or custom tickers. It calculates simple descriptive metrics such as open/close change, percent change, high/low, volume, and a basic recent trend indicator. There is no news ingestion, no event detection, no causal analysis, and no predictive modeling of ripple effects across time horizons. While the description mentions price tracking for several asset classes, the primary promised behavior is an impact analyzer with forecasting, which this code does not implement. Additionally, the code supports currency instruments, which are not mentioned in the declared purpose. Therefore, the description materially overstates and misrepresents the code’s behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises an analyzer that both tracks multiple asset prices and predicts market effects across different time horizons. The supplied code does not implement any pricing, forecasting, or analytical logic. Its actual function is limited to fetching and formatting RSS news/headlines from external sources. While 'fetch breaking news' is consistent with part of the description, the primary purpose is materially narrower and different from the claimed impact-analysis system.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill invokes local Python tools that can perform shell execution, network access, and likely file reads, yet the manifest does not declare any explicit tool scope or permissions boundary. That makes the skill harder to review and govern, and can lead to over-privileged execution where callers or platforms do not clearly understand what capabilities are being granted.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The title and prescribed output format are written in Chinese, and the tool details set `--lang` default to `zh`, indicating a language preference baked into the skill. There is no explicit opt-in, user choice, or documented region-specific justification for requiring Chinese output.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The activation keywords are very broad and cover generic discussion of news, markets, gold, oil, bitcoin, stocks, and event analysis in both Chinese and English. Over-broad triggers increase the chance the skill activates unintentionally and performs network or shell-backed actions in contexts where the user did not clearly request this tool, which can expand attack surface and create consent/confusion problems.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This Python file is in scope for SQP-3 because it contains extensive natural-language output strings. The script consistently emits Chinese-only messages and report sections, including errors, warnings, and final analysis text, with no mechanism for users to choose language or locale; that is a language/locale policy violation under the rule.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd = [sys.executable, script_path] + args_list + ['--json']
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
        if result.returncode == 0 and result.stdout.strip():
            return json.loads(result.stdout)
        else:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code embeds Chinese asset names and Chinese status/output strings throughout the skill, including headings, labels, trends, and warnings. Because the file provides no option to select language or locale, it imposes a specific language on users, which matches the natural-language locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code emits multiple user-facing strings only in Chinese, including headline labels, search results, and error messages. The skill does not provide an opt-in for output language, so it enforces a specific locale rather than offering a language choice.

Unpinned Dependencies

Low
Category
Supply Chain
Content
yfinance>=0.2.36
Confidence
90% confidence
Finding
The dependency is specified with a lower-bound only constraint (`yfinance>=0.2.36`), which allows future unreviewed versions to be installed. This creates supply-chain and reproducibility risk because a later compromised or breaking release could be pulled into the environment without explicit approval.

Static analysis

No suspicious patterns detected.