Back to skill

Security audit

Tavily + Zhipu Web Search

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real web-search skill, but it can automatically use a locally stored generic API key and send it to Zhipu, which is broader than the documentation clearly explains.

Review before installing. Use only dedicated TAVILY_API_KEY and ZHIPU_API_KEY values, and avoid relying on ~/.openclaw/openclaw.json until the generic credential lookup is removed or restricted. Do not submit secrets, private customer data, or proprietary terms as search queries unless you are comfortable sending them to Tavily or Zhipu.

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/search.py:48
Finding

Unrelated Provider Credential May Be Disclosed to Zhipu

Content
View full analysis

Vulnerability Details

File Location: scripts/search.py, lines 48–60 and 69–73
Vulnerability Type: Credential selection and unintended disclosure
Risk Level: Medium

Vulnerable Code

python
def _zhipu_key():
    key = os.environ.get("ZHIPU_API_KEY")
    if key:
        return key
    config_path = os.path.expanduser("~/.openclaw/openclaw.json")
    if os.path.exists(config_path):
        try:
            with open(config_path) as f:
                cfg = json.load(f)
            for p in ["generic", "glm"]:
                k = cfg.get("models", {}).get("providers", {}).get(p, {}).get("apiKey", "")
                if k:
                    return k
        except Exception:
            pass
    return ""

The returned value is subsequently placed in the authorization header:

python
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}",
    "Accept": "application/json, text/event-stream",
}

Requests carrying that header are sent to the fixed Zhipu endpoint:

python
req = urllib.request.Request(
    ZHIPU_MCP_URL,
    data=init_payload,
    headers=headers,
    method="POST",
)

Technical Analysis

The _zhipu_key() function treats models.providers.generic.apiKey as a Zhipu credential without checking which service the generic provider represents. Because generic is checked before glm, any nonempty generic provider key is selected even when a valid Zhipu-specific glm key is available.

The selected value is used as a bearer credential in HTTPS requests to https://open.bigmodel.cn/api/mcp/web_search_prime/mcp. If the generic key belongs to another service, the Skill discloses an unrelated credential to Zhipu. Reading and transmitting arbitrary provider credentials exceeds the minimum privilege required for the declared web-search fallback.

The use of HTTPS protects the credential in transit from ordinary passive interception, but it does not prevent disclosure to the d ...[truncated 1326 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove generic from automatic Zhipu credential discovery and accept only an explicitly scoped credential:
python
def _zhipu_key():
    key = os.environ.get("ZHIPU_API_KEY")
    if key:
        return key

    config_path = os.path.expanduser("~/.openclaw/openclaw.json")
    try:
        with open(config_path, encoding="utf-8") as f:
            cfg = json.load(f)
        return (
            cfg.get("models", {})
               .get("providers", {})
               .get("glm", {})
               .get("apiKey", "")
        )
    except (OSError, ValueError, TypeError):
        return ""
  1. Prefer requiring ZHIPU_API_KEY explicitly rather than inferring credentials from broadly named provider entries.
  2. If provider-based discovery must remain, verify that the provider identifier and configured base URL match a strict allowlist of approved Zhipu endpoints before using its key.
  3. Never send a credential selected from one provider configuration to another provider's endpoint.
  4. Document the exact credential lookup behavior in SKILL.md so users understand which local configuration fields may be read.
  5. Add tests confirming that:
    • generic.apiKey is never returned as a Zhipu key.
    • glm.apiKey is selected only for Zhipu.
    • An explicit ZHIPU_API_KEY takes precedence.
    • Absence of a correctly scoped key fails closed without making an authenticated request.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes code with network access and reads credentials from environment variables, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. This creates a governance gap: users and host systems cannot easily understand or constrain what the skill is allowed to access, increasing the chance of unintended data exposure or over-broad execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation tells users to submit arbitrary search queries to third-party providers but does not warn that those queries will be transmitted externally. Users may unknowingly include sensitive internal data, credentials, personal information, or proprietary terms in searches, causing avoidable privacy and confidentiality leaks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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
# ── Tavily ──────────────────────────────────────────────────────────────────

TAVILY_URL = "https://api.tavily.com/search"


def _tavily_key():

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The fallback path reads an API key from a local user config file (~/.openclaw/openclaw.json) even though the skill’s stated purpose is just to perform web search. This creates an implicit secret-access behavior: invoking the skill may consume credentials the user did not intend to expose to this script or this provider, expanding trust boundaries and increasing the chance of unintended third-party data transmission.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The fallback request hardcodes location='cn', which can alter search results and cause the user’s query to be processed under a China-specific locale without opt-in. In a web-search skill, locale affects what data is sent, how it is handled, and what content is returned, making this a privacy and policy concern rather than a mere formatting preference.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The unified search function silently falls back from Tavily to Zhipu and sends the user's query to a different third-party service without any prior disclosure or consent. If queries contain sensitive business, personal, or regulated information, this changes the data recipient unexpectedly and can violate privacy expectations or policy constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script's user-facing output strings are hardcoded in Chinese, including errors, status text, and usage context, without any indication that users can choose another language. This creates a language/locale policy issue because the skill imposes a specific language without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The code reads API credentials from a local config file without informing the user, which is a transparency and consent issue. While it does not directly exfiltrate the key in output, it can cause unexpected use of stored credentials and hidden coupling to unrelated local configuration.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.