Back to skill

Security audit

Baidu web search

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it has an undisclosed environment-controlled proxy path that can redirect search queries and a session identifier outside the stated Baidu endpoint.

Install only if you are comfortable sending search queries to Baidu and storing a Baidu API key in local OpenClaw configuration. Before use, restrict permissions on the OpenClaw config file, avoid placing sensitive secrets in search queries, and review or remove the DUMATE_SCHEDULER_URL proxy behavior unless you trust and control that scheduler environment.

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:31
Finding

Unvalidated Environment-Controlled Proxy Exposes Search Queries and Session Identifiers

Content
View full analysis

Vulnerability Details

File Location: scripts/search.py, lines 31-58
Vulnerability Type: Unvalidated network destination and sensitive-data disclosure
Risk Level: High

Vulnerable Code

python
def resolve_sandbox_url(original_url: str) -> Tuple[str, Dict[str, str]]:
    """若当前在沙盒环境中,将目标 URL 替换为代理 URL,并返回需要附加的 headers。"""
    session_id = os.environ.get("DUMATE_SESSION_ID")
    scheduler_url = os.environ.get("DUMATE_SCHEDULER_URL")

    headers = {
        "Content-Type": "application/json",
    }
    if not session_id or not scheduler_url:
        # 优先使用传入的 api_key,否则从环境变量读取
        api_key = os.environ.get("BAIDU_API_KEY")
        if not api_key:
            raise ValueError("未设置 API Key,请通过环境变量 BAIDU_API_KEY 设置或使用")
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}",
            "X-Appbuilder-From": "openclaw",
        }
        return original_url, headers

    parsed = urlparse(original_url)
    proxy_url = f"{scheduler_url}/api/qianfanproxy{parsed.path}"
    if parsed.query:
        proxy_url += f"?{parsed.query}"

    headers.update({
        "Host": parsed.netloc,
        "X-Dumate-Session-Id": session_id,
        "X-Appbuilder-From": "desktop",
    })
    return proxy_url, headers

The returned URL and headers are subsequently used by the following request at lines 11-16:

python
url = "https://qianfan.baidubce.com/v2/ai_search/web_search"
url, headers = resolve_sandbox_url(url)
# 使用POST方法发送JSON数据
response = requests.post(url, json=requestBody, headers=headers)
response.raise_for_status()
results = response.json()

Technical Analysis

The Skill's declared purpose requires sending search queries to Baidu's AI Search API. The direct request to the fixed HTTPS origin qianfan.baidubce.com is therefore consistent with its stated functionality.

However, when both DUMATE_SESSION_ID and DUMATE_SCHEDULER_URL are present, the implementation silently repl ...[truncated 2688 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the sandbox proxy branch if it is not essential to the Skill's declared search functionality.
  2. If proxying is required, use a fixed trusted proxy origin or validate the destination against a strict hostname allowlist.
  3. Require the https scheme and reject HTTP, unsupported schemes, embedded credentials, fragments, unexpected ports, and malformed origins.
  4. Parse the configured proxy URL with urllib.parse.urlparse() and construct the destination from validated components rather than concatenating an unrestricted string.
  5. Document the proxy behavior, transmitted fields, and trust assumptions in SKILL.md.
  6. Avoid sending a reusable session identifier where possible. Otherwise, use a narrowly scoped, short-lived proxy token.
  7. Prevent unintended redirect-based data disclosure by disabling redirects or validating every redirect destination.
  8. Add a bounded connection and response timeout to the request.
  9. Remove or redact the input logging at scripts/search.py:63, where the full parsed query is printed, to reduce secondary exposure through logs.
  10. Add tests confirming that HTTP URLs, unapproved hosts, embedded credentials, and unexpected ports are rejected.

A hardened design should resemble:

python
ALLOWED_PROXY_HOSTS = {"trusted-scheduler.example"}

parsed_scheduler = urlparse(scheduler_url)
if (
    parsed_scheduler.scheme != "https"
    or parsed_scheduler.hostname not in ALLOWED_PROXY_HOSTS
    or parsed_scheduler.username is not None
    or parsed_scheduler.password is not None
    or parsed_scheduler.fragment
    or parsed_scheduler.port not in (None, 443)
):
    raise ValueError("Untrusted scheduler URL")

proxy_url = (
    f"https://{parsed_scheduler.hostname}"
    f"/api/qianfanproxy{urlparse(original_url).path}"
)

response = requests.post(
    proxy_url,
    json=requestBody,
    headers=headers,
    timeout=(5, 30),
    allow_redirects=False,
)
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill explicitly requires an environment variable containing an API key and performs web search operations, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens least-privilege controls and makes the skill's access to secrets and network capabilities less transparent to reviewers and policy enforcement, increasing the chance of unintended data exposure or misuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The usage examples exclusively use Chinese queries such as "人工智能", "最新新闻", and "旅游景点", which indicates the skill is framed around a specific language/locale. The file does not state that Chinese is optional, does not offer a language choice, and does not justify a locale-specific restriction, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/apikey-fetch.md (reported line 11)May include surrounding context.

md
Visit: **https://console.bce.baidu.com/ai-search/qianfan/ais/console/apiKey**

- Log in to your Baidu Cloud account
- Create an application or view existing API keys
- Copy your **API Key** (only API Key is needed)

### 2. Configure OpenClaw

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide explicitly instructs users to place a live API key into a plaintext local configuration file and does not mention file permissions, secret storage, or the security implications of writing credentials to disk. This increases the chance of credential disclosure through local compromise, backups, logs, dotfile syncing, or accidental sharing of the configuration file.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/search.py (reported line 15)May include surrounding context.

python
url = "https://qianfan.baidubce.com/v2/ai_search/web_search"
    url, headers = resolve_sandbox_url(url)
    # 使用POST方法发送JSON数据
    response = requests.post(url, json=requestBody, headers=headers)
    response.raise_for_status()
    results = response.json()
    if "code" in results:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code sends the provided request body, including the user's query content, to Baidu's web search API via an outbound POST request. There is no confirmation prompt, user-facing warning, or explanatory comment/docstring near the operation to disclose that user-supplied data is being transmitted to an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script reads the BAIDU_API_KEY credential from the environment to authorize requests, but there is no user-facing notice, comment, or docstring explaining this sensitive credential access. Under the rule, access to credentials should have some visible disclosure unless already documented elsewhere.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.