Back to skill

Security audit

Baidu Finance Search

Security checks for vulnerabilities and agentic risk

Overview

This finance-search skill does what it says, but its HTTPS request deliberately disables certificate checks while sending an API key and user queries, which makes the integration unsafe to install without review.

Review before installing. The main issue is not the finance-search purpose, but the unsafe TLS configuration in scripts/search.py; use only after removing the disabled certificate checks, and avoid sending confidential trading plans, personal data, or sensitive business research to the Baidu API. Keep the Baidu API key low-privilege and rotate it if this version has already been used on untrusted networks.

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

Error
Location
scripts/search.py:139
Finding
HTTPS Certificate and Hostname Verification Disabled## Vulnerability Details **File Location**: `scripts/search.py`, lines 139–147 **Vulnerability Type**: Improper TLS certificate validation **Risk Level**: High ### Vulnerable Code ```python # 禁用 SSL 验证 ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE try: with urllib.request.urlopen(req, timeout=60, context=ctx) as response: result = json.loads(response.read().decode("utf-8")) ``` ### Technical Analysis The script creates a TLS context but explicitly disables both hostname validation and certificate-chain verification. Consequently, HTTPS encryption is used without authenticating that the remote endpoint is actually `qianfan.baidubce.com`. The request carries the Baidu API key in the `Authorization: Bearer` header. Its body may contain financial queries, custom instructions, and caller-supplied conversation history. A network-positioned attacker can present an arbitrary certificate, impersonate the Baidu endpoint, decrypt the request, and provide a forged response because the client accepts certificates that are untrusted or issued for a different hostname. ### Attack Path 1. A user invokes the Skill to submit a financial search. 2. An attacker obtains a network interception position, such as through a malicious proxy, compromised router, hostile Wi-Fi network, or DNS manipulation. 3. The attacker redirects or intercepts the connection intended for `qianfan.baidubce.com`. 4. The attacker's server presents an arbitrary TLS certificate. 5. Because `check_hostname` is `False` and `verify_mode` is `ssl.CERT_NONE`, the client accepts the certificate. 6. The client transmits the Bearer API key and request body to the impersonated endpoint. 7. The attacker captures the credential and potentially sensitive request data. 8. The attacker can return fabricated JSON containing manipulated financial analysis or references, which the script formats and presents as a legitimate result. ### Impact Assessment Su ...[truncated 616 chars]
Remediation
## Remediation Suggestions Remove the custom TLS context and allow `urllib` to use certificate and hostname verification through the operating system's trusted CA store: ```python try: with urllib.request.urlopen(req, timeout=60) as response: result = json.loads(response.read().decode("utf-8")) ``` Alternatively, create a secure context without weakening its defaults: ```python ctx = ssl.create_default_context() try: with urllib.request.urlopen(req, timeout=60, context=ctx) as response: result = json.loads(response.read().decode("utf-8")) ``` If a private CA is required, load only the necessary trusted CA bundle with `cafile` or `load_verify_locations()`. Keep `check_hostname = True` and `verify_mode = ssl.CERT_REQUIRED`. Additional hardening should include: - Fail closed on certificate or hostname validation errors. - Never add an option that silently disables TLS verification in production. - Rotate the Baidu API key if the vulnerable implementation has been used over untrusted networks. - Restrict the API key's permissions and quota to the minimum required. - Add a regression test confirming that self-signed, expired, and hostname-mismatched certificates are rejected.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (10)

Tainted flow: 'req' from os.environ.get (line 146, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
ctx.verify_mode = ssl.CERT_NONE
    
    try:
        with urllib.request.urlopen(req, timeout=60, context=ctx) as response:
            result = json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        error_body = e.read().decode("utf-8")
Confidence
98% confidence
Finding
The code disables TLS certificate and hostname verification before sending an authenticated HTTPS request containing the Bearer API key. This allows a man-in-the-middle attacker to intercept or modify the request and response, exposing credentials and tampering with search results.

Credential Access

High
Category
Privilege Escalation
Content
api_key = os.environ.get("BAIDU_API_KEY")
    
    if not api_key:
        env_file = os.path.join(os.path.dirname(__file__), "..", "..", ".env")
        if os.path.exists(env_file):
            with open(env_file, "r") as f:
                for line in f:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises code-capable behavior involving environment variables, file reads, and outbound network access, but it does not declare any tool scope or permissions in the manifest. This weakens least-privilege controls and makes it harder for users or a host platform to understand and constrain what the skill can access before execution.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The documentation states that user queries are sent to Baidu's remote AI search API using bearer-token authentication, but it does not clearly warn users that their inputs leave the local environment and are transmitted to a third party. In a finance-search context, queries may contain sensitive investment interests, strategy details, or proprietary research topics, creating privacy and compliance risks.

Intent-Code Divergence

Medium
Confidence
77% confidence
Finding
The top-level documentation frames the skill as a customized Baidu finance search following a specific methodology and focused on sites like Xueqiu, Zhihu, Eastmoney, and Tonghuashun. In practice, callers can fully override both the system instruction and messages at L86-L87 and L109-L120, allowing use as a general-purpose AI search front end rather than the documented constrained finance-search behavior.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The default instruction hard-codes a Chinese-finance focus and explicitly targets Chinese communities, which effectively constrains the skill's language/locale behavior by default. There is no indication in the file that users are offered a language or locale choice before this default is applied.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The manifest describes a finance-search skill for querying web sources, which makes outbound HTTP requests an expected implementation detail. However, falling back to reading a local .env file adds local filesystem access to retrieve secrets, which is not part of the stated user-facing purpose and expands the skill's capability beyond simple search behavior.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This code builds a request body containing the user's query, optional conversation history, and instruction, then sends it to an external Baidu API. While the function docstring describes that a search is performed, there is no user-facing print/log/confirmation warning in the code that user-supplied content will be transmitted to a remote service.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
Natural-language content in the skill name/description and usage sections is presented exclusively in Chinese, with no indication that users can select another language or that the locale restriction is intentional. For a general-purpose skill, forcing a single language without opt-in can be a policy concern.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The script reads a sensitive credential from the BAIDU_API_KEY environment variable and, if absent, from a local .env file. Although this is common implementation behavior, the code provides no user-facing notice that it will access local credentials to authenticate outbound requests.

Static analysis

No suspicious patterns detected.