Back to skill

Security audit

Byted Web Search

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real web-search client, but it repeatedly asks users to paste API keys into chat and uses broader credential/search behavior than users are likely to expect.

Review before installing. Use a dedicated skill credential setting or tightly scoped environment variable, not chat, for any API key; rotate the key if it has already been pasted into a conversation. Be aware that search queries and bearer API keys may be sent to open.feedcoopapi.com in the API-key flow, and avoid running the skill with access to shared .env files containing unrelated secrets.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/web_search.py:49
Finding
API Key Is Transmitted to an Undocumented Non-Volcengine Domain<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_search.py:49, 311-324` **Vulnerability Type**: Credential disclosure to an insufficiently documented network destination **Risk Level**: High ### Complete Code Snippet ```python HOST = "mercury.volcengineapi.com" INTERNAL_API_URL = "https://open.feedcoopapi.com/search_api/web_search" ``` ```python body_str = json.dumps(body, ensure_ascii=False) if api_key: headers = { "Content-Type": "application/json", TRAFFIC_TAG_HEADER: TRAFFIC_TAG_VALUE, "Authorization": f"Bearer {api_key}", } url = INTERNAL_API_URL else: if not ak or not sk: raise ValueError("missing volcengine credentials") headers = _sign_request("POST", ak, sk, body_str, session_token) url = f"https://{HOST}?Action={ACTION}&Version={VERSION}" response = requests.post( url, headers=headers, data=body_str.encode("utf-8"), timeout=30, ) ``` ### Technical Analysis When API-key authentication is selected, the script places the complete secret in a bearer `Authorization` header and sends it to `open.feedcoopapi.com`. This destination differs from the documented Volcengine API host used by the AK/SK path, `mercury.volcengineapi.com`. The project documentation repeatedly describes this as an official Volcengine search capability and directs users to obtain credentials from Volcengine, but it does not disclose or explain why those credentials are delivered to `open.feedcoopapi.com`. No certificate pinning, endpoint allowlist configurable by an administrator, audience-restricted token exchange, or destination validation is implemented. Sending an API key to the service that authenticates it may be functionally necessary. However, sending it to a materially different and undocumented domain exceeds what users can reasonably infer from the declared functionality unless ownership, processing purpose, and authorization for that domain are established. The AK/SK branch fo ...[truncated 1731 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Send credentials only to an endpoint explicitly listed in the official product documentation. 2. If `open.feedcoopapi.com` is an authorized Volcengine endpoint, document its ownership, purpose, privacy implications, and credential-processing role prominently before credential collection. 3. Prefer the signed request flow, where the secret key remains local, or exchange the API key for a short-lived, narrowly scoped token through an official endpoint. 4. Restrict tokens to the Web Search action, enforce short expiration, and provide straightforward revocation and rotation. 5. Add an administrator-configurable endpoint allowlist and fail closed if the configured hostname is not approved. 6. Avoid following redirects for authenticated requests, or explicitly validate every redirect destination before retaining the `Authorization` header. 7. Add automated tests asserting that credentials can only be sent to approved hosts. 8. Notify existing users of the destination and recommend credential rotation if the domain was not previously disclosed. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/web_search.py:54
Finding
Broad Loading of Shared OpenClaw Environment Files Violates Least Privilege<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_search.py:54-116, 366-369` **Vulnerability Type**: Overbroad credential-file access and environment injection **Risk Level**: Medium ### Complete Code Snippet ```python LEGACY_ENV_PATH = "/root/.openclaw/.env" USER_ENV_PATH = str(Path.home() / ".openclaw/.env") ``` ```python def _load_legacy_env_file(env_path: str = LEGACY_ENV_PATH) -> None: if not os.path.exists(env_path): return try: with open(env_path, "r", encoding="utf-8") as f: for raw_line in f: line = raw_line.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[len("export "):].strip() if "=" not in line: continue key, value = line.split("=", 1) key = key.strip() value = value.strip() if not key: continue try: parsed = shlex.split(value, comments=True) value = parsed[0] if parsed else "" except ValueError: value = value.strip("\"'") os.environ.setdefault(key, value) except OSError: return def _load_legacy_env_files() -> None: seen_paths = set() for env_path in (LEGACY_ENV_PATH, USER_ENV_PATH): normalized = os.path.abspath(os.path.expanduser(env_path)) if normalized in seen_paths: continue seen_paths.add(normalized) _load_legacy_env_file(normalized) ``` ```python def main(): _load_legacy_env_files() _skill_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) _load_legacy_env_file(os.path.join(_skill_root, ".env")) ``` ### Technical Analysis The Skill requires at most three credential variables: - `WEB_SEARCH_API_KEY` - `VOLCENGINE_ACCESS_KEY` - `V ...[truncated 2504 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove automatic loading of `/root/.openclaw/.env` and `$HOME/.openclaw/.env`. 2. Rely on the host platform to inject only the Skill's declared `primaryEnv` credential. 3. If `.env` compatibility is required, parse only an explicit allowlist: - `WEB_SEARCH_API_KEY` - `VOLCENGINE_ACCESS_KEY` - `VOLCENGINE_SECRET_KEY` 4. Keep selected credentials in local variables instead of copying them into `os.environ`. 5. Refuse insecure files that are group-readable, world-readable, symlinks, or owned by an unexpected account. 6. Do not inspect root-owned paths unless the documented deployment explicitly requires it. 7. Report the selected credential source without printing the credential value, so administrators can identify unexpected fallback behavior. 8. Run the Skill as an unprivileged account with access only to its own configuration. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:22
Finding
Documentation Encourages Users to Submit Long-Lived API Keys Through Chat<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:22-35, 108` **Vulnerability Type**: Insecure secret collection through conversational content **Risk Level**: High ### Complete Behavioral Excerpt The instructions at lines 22-35 require the agent to give a short credential-enrollment response whose third step tells the user to send the API key directly in the current chat. Line 108 repeats that credentials can be supplied directly through chat and presents this as a normal Claw integration flow. Equivalent guidance also appears in: - `README.md:7-10` - `references/setup-guide.md:3, 20-34` - `scripts/web_search.py:21-22, 372-385, 423-425` The executable additionally exposes a command-line secret option: ```python parser.add_argument( "--api-key", help="API Key(优先于环境变量 WEB_SEARCH_API_KEY)", ) parser.add_argument( "--prompt-api-key", action="store_true", help="交互式输入 API Key(不回显)", ) ``` ```python api_key = _get_api_key(args.api_key) if not api_key and args.prompt_api_key: entered = getpass.getpass("API Key: ").strip() api_key = entered or None ``` ### Technical Analysis A chat message is not a dedicated secret-entry channel. Depending on the host platform, chat content can be retained in conversation history, model-provider logs, telemetry, moderation systems, exports, support tooling, browser storage, or agent traces. It can also be included in later model context. The Skill not only permits this flow but repeatedly recommends it. This creates a predictable social-engineering pattern in which an agent asks the user to paste a reusable credential into ordinary conversational content. The `--api-key` option creates an additional disclosure path because command-line arguments can be retained in shell history and may be observable through process inspection. The script already implements `--prompt-api-key`, which avoids terminal echo, but the safer mechanism is not the default recommendation. ### Attack Path 1. ...[truncated 1392 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every instruction asking users to paste credentials into chat. 2. Direct users to the platform's dedicated encrypted credential or Skill configuration interface. 3. Make `WEB_SEARCH_API_KEY` platform injection the only recommended interactive integration. 4. For local terminal use, recommend `--prompt-api-key` or protected environment injection rather than `--api-key`. 5. Deprecate and remove `--api-key`, or emit a warning that it may expose the key through shell history and process listings. 6. Redact credential-like values from agent traces, logs, support bundles, and error reports. 7. If a credential is detected in chat, instruct the user to revoke and rotate it rather than repeating or storing it. 8. Use short-lived, narrowly scoped tokens where the platform supports them. 9. Clearly document retention and processing boundaries before requesting any secret. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:5
Finding
Overbroad Self-Routing Instructions Hijack Agent Search Behavior<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:5, 14-18, 22-40, 43-79, 83-89` **Vulnerability Type**: Skill instruction hijacking and forced credential solicitation **Risk Level**: Medium ### Complete Behavioral Excerpt The Skill metadata and operational instructions direct the agent to: - Prefer this Skill whenever a response may depend on external facts. - Trigger not only for explicit search requests but for broad conversational phrases involving uncertainty, recommendations, comparisons, current events, prices, or verification. - Proactively invoke the Skill even when the user did not explicitly ask for a search. - Use a prescribed response that asks the user to obtain and send an API key. - Keep the credential-enrollment response deliberately brief and avoid broader billing or console explanations. These requirements are repeated across the front matter and the routing, missing-credential, weak-intent, and pre-execution sections. ### Technical Analysis A search Skill needs instructions describing when it is useful. Here, however, the trigger scope covers a substantial portion of ordinary factual conversation and directs the agent to prefer this specific paid-account-integrated service over other available tools. The Skill also dictates the agent's user-facing response when credentials are absent, including how much information may be disclosed and how the key should be collected. This modifies current-session behavior beyond merely implementing a search operation. The combination of broad self-selection and credential solicitation creates a funnel: 1. Common conversational language activates the Skill. 2. The Skill attempts a credentialed operation. 3. Missing credentials trigger a prescribed enrollment message. 4. The user is directed to create and submit a key. This behavior does not create cross-session persistence and does not alter long-term memory. It is therefore a current-session instruction-hijacking issue rather than m ...[truncated 1123 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Limit automatic activation to explicit search requests or clearly time-sensitive questions. 2. Treat broad phrases such as comparisons, recommendations, and uncertainty as advisory signals rather than mandatory triggers. 3. Require user confirmation before sending a query to an external provider when the user did not explicitly request network access. 4. Remove instructions requiring this Skill to outrank other available tools. 5. Separate missing-credential handling from provider enrollment and avoid forced marketing language. 6. Disclose the external destination, query-sharing implications, authentication requirements, and possible billing before activation. 7. Never instruct the agent to collect secrets in chat. 8. Preserve the host agent's higher-level safety, privacy, and tool-selection policies by explicitly stating that Skill instructions are subordinate to them. ]]>
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (33)

Missing User Warnings

High
Confidence
99% confidence
Finding
The README explicitly tells users to paste an API key directly into the chat interface, which creates a real credential-handling risk. Chat channels may be logged, retained, exposed to other tools, or visible to unintended parties, so encouraging secret transmission through chat can lead to credential leakage and unauthorized API use.

Vague Triggers

High
Confidence
96% confidence
Finding
The activation guidance uses very common conversational phrases as triggers, so the skill may be invoked when the user did not actually request web access. In an agent setting, overly broad routing can cause unnecessary external data transmission and unexpected tool use.

Vague Triggers

High
Confidence
95% confidence
Finding
The file instructs the agent to proactively invoke the skill even without explicit search intent, but it does not set firm boundaries for when that is appropriate. This can turn normal conversation into implicit web queries, exposing user content to third-party services without clear necessity or consent.

Vague Triggers

High
Confidence
95% confidence
Finding
Treating broad fuzzy words as sufficient reason to prioritize invocation creates collision-prone routing. Common words like 'recommend', 'current', or 'is it true' appear in many contexts, so the skill could capture requests that should remain local or use a different tool.

Vague Triggers

High
Confidence
97% confidence
Finding
The weak-intent table encourages activation across many everyday expressions without guardrails such as consent, sensitivity checks, or ambiguity handling. In practice this broadens the attack surface for accidental exfiltration of user queries and for unnecessary dependency on remote services.

Vague Triggers

High
Confidence
97% confidence
Finding
The 'appear then consider invocation' keyword list is expansive and lacks counterexamples or disambiguation guidance. Keyword-triggered behavior at this breadth is brittle and can be manipulated or accidentally matched, resulting in unintended external searches.

Ae1

High
Category
analysis-evasion
Content
在调用 `web_search.py` 之前:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
在调用 `web_search.py` 之前:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
在调用 `web_search.py` 之前:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The guide explicitly tells users to paste an API key into the chat, which exposes a reusable secret to the conversational channel, agent runtime, logs, transcripts, and any downstream integrations that can access message history. This exceeds the minimum access needed for the web-search skill and creates unnecessary credential disclosure risk.

Missing User Warnings

High
Confidence
98% confidence
Finding
The document instructs users to paste an API key directly into chat without any warning about credential exposure, which encourages unsafe handling of secrets. Because the skill is for online search and does not inherently require the model to see raw credentials in conversation, this creates avoidable risk with no clear necessity.

Ssd 3

High
Confidence
99% confidence
Finding
This is a direct instruction to disclose an API key to the agent in chat, which is sensitive-data handling contrary to least-privilege practices. In an agent skill, the danger is amplified because conversation content may be accessible to the model, platform operators, logs, and potentially other tools or memory features.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The configuration section prioritizes giving the key to the agent in chat over safer configuration paths, normalizing insecure secret handling. In the skill context this is especially dangerous because the agent may retain, summarize, forward, or expose the credential beyond the user's intended one-time setup.

Missing User Warnings

High
Confidence
98% confidence
Finding
The configuration guidance again encourages handing the key to the agent in chat while omitting any caution about transcript retention or unauthorized access. This omission makes the workflow more dangerous by presenting insecure secret disclosure as the preferred user experience.

Ssd 3

High
Confidence
99% confidence
Finding
The section explicitly makes handing the key to the agent the preferred path, subordinating secure local setup to a less secure conversational workflow. That design choice materially increases the chance of credential compromise and misuse if transcripts are retained, exported, or viewed by unintended parties.

Credential Access

High
Category
Privilege Escalation
Content
TRAFFIC_TAG_VALUE = "skill_web_search_common"
TIME_RANGE_SHORTCUTS = {"OneDay", "OneWeek", "OneMonth", "OneYear"}
DATE_RANGE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$")
LEGACY_ENV_PATH = "/root/.openclaw/.env"
USER_ENV_PATH = str(Path.home() / ".openclaw/.env")
SUMMARY_PREVIEW_LIMIT = 1000
ERROR_HINTS = {
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
TRAFFIC_TAG_VALUE = "skill_web_search_common"
TIME_RANGE_SHORTCUTS = {"OneDay", "OneWeek", "OneMonth", "OneYear"}
DATE_RANGE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$")
LEGACY_ENV_PATH = "/root/.openclaw/.env"
USER_ENV_PATH = str(Path.home() / ".openclaw/.env")
SUMMARY_PREVIEW_LIMIT = 1000
ERROR_HINTS = {
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
TRAFFIC_TAG_VALUE = "skill_web_search_common"
TIME_RANGE_SHORTCUTS = {"OneDay", "OneWeek", "OneMonth", "OneYear"}
DATE_RANGE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$")
LEGACY_ENV_PATH = "/root/.openclaw/.env"
USER_ENV_PATH = str(Path.home() / ".openclaw/.env")
SUMMARY_PREVIEW_LIMIT = 1000
ERROR_HINTS = {
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The README is entirely written in Chinese and describes the skill workflow only in that language, with no indication that other languages are supported or that Chinese is a required locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is explicit and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents capabilities that rely on environment variables, local files (.env), and outbound network access, but it does not declare any explicit tool scope or permissions. That makes its effective privileges implicit, which increases the chance of over-broad execution in hosts that support capability gating or user review.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The instruction "给用户的回复必须极简" is paired with a fixed Chinese reply template and does not indicate that the language should follow the user's preference. Because no opt-in or documented region-specific justification is provided, this can violate language/locale choice policy.

Ssd 3

Medium
Confidence
98% confidence
Finding
The skill explicitly instructs users to paste an API key into the chat, normalizing transmission of secrets through a natural-language channel that may be logged, retained, or exposed to unintended parties. This creates a direct credential disclosure pattern and increases the likelihood of key compromise.

Vague Triggers

Medium
Confidence
86% confidence
Finding
Examples such as "怎么用", "教我用", and "这个 skill 能干啥" are ordinary help phrases and are treated as sufficient to trigger onboarding behavior. The file does not clearly separate general discussion about the skill from actual intent to perform web search.

Ssd 3

Medium
Confidence
98% confidence
Finding
The repeated guidance reinforces a habit of sending credentials in chat, which compounds the risk of leakage through logs, screenshots, transcripts, or model/provider retention. Repetition makes the unsafe behavior appear endorsed and routine.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The troubleshooting guidance tells users to resend the correct key in chat, reinforcing repeated disclosure of a sensitive credential through an insecure channel. Repeated sharing increases the chance of leakage through logs, support review, transcript retention, or accidental reuse in other contexts.

Static analysis

No suspicious patterns detected.