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

Content
View full analysis

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
View 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
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.

Content

Scanner excerpt · scripts/search.py (reported line 154)May include surrounding context.

python
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")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/search.py (reported line 40)May include surrounding context.

python
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:

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.