Back to skill

Security audit

必应搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent, but its webpage fetcher can request arbitrary URLs without private-network or response-size safeguards.

Install only if you are comfortable giving the skill outbound web-fetch capability from the agent's environment. Avoid using it where the agent can reach internal dashboards, localhost services, cloud metadata endpoints, or other private network resources unless those destinations are blocked outside the skill.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
bing-search.js:151
Finding
Server-Side Request Forgery Through Arbitrary URL Fetching<![CDATA[ ## Vulnerability Details **File Location**: `bing-search.js:151-159` and `bing-search.js:213-215` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```js async function crawlWebpage(url) { if (isBlacklisted(url)) { throw new Error('该网站在黑名单中,无法抓取'); } return new Promise((resolve, reject) => { const client = url.startsWith('https') ? https : http; const req = client.get(url, { ``` The URL is obtained directly from command-line input: ```js } else if (command === 'fetch') { const url = args[1]; const result = await crawlWebpage(url); ``` ### Technical Analysis The `fetch` operation accepts an attacker-controlled URL and passes it directly to Node.js `http.get()` or `https.get()`. It does not parse and validate the destination hostname, resolved IP addresses, destination port, or URL protocol against a security policy. The existing `isBlacklisted()` check only searches the raw URL for a small set of public website domain substrings. It does not block sensitive destinations such as: - IPv4 and IPv6 loopback addresses - Private network address ranges - Link-local addresses - Cloud instance metadata services - Internal DNS names - Services listening on nonstandard ports The network request executes with the network access available to the Node.js process. Consequently, the function can reach services that may not be directly accessible to the party controlling the input. ### Attack Path 1. An attacker causes the Skill to invoke the `fetch` command with a URL targeting an internal resource, such as a loopback service, private-network host, or cloud metadata endpoint. 2. The URL does not contain one of the public domains in `BLACKLIST`, so `isBlacklisted()` returns `false`. 3. `crawlWebpage()` passes the URL directly to `http.get()` or `https.get()`. 4. The Node.js process connects to the internal destination using its own network privileges. 5. The response is converted ...[truncated 1000 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse input using `new URL(url)` and reject malformed URLs. 2. Permit only exact `http:` and `https:` protocols. 3. Resolve the hostname before connecting and reject every resolved address belonging to: - IPv4 or IPv6 loopback ranges - RFC 1918 private ranges - Link-local ranges - Multicast and unspecified ranges - Reserved or documentation ranges - Known cloud metadata destinations 4. Prevent DNS rebinding by connecting only to the validated resolved address while preserving the intended hostname for TLS verification and the HTTP `Host` header. 5. Prefer an explicit destination-domain allowlist when the business requirements permit it. 6. Restrict destination ports to expected web ports unless additional ports are explicitly required. 7. Node.js does not automatically follow redirects in this implementation. If redirect support is added later, validate every redirect destination using the same rules before following it. 8. Apply outbound firewall or proxy controls so the Skill process cannot access internal networks or metadata services. 9. Add security tests covering IPv4, IPv6, integer or encoded address forms, internal DNS names, DNS rebinding, loopback services, private ranges, link-local metadata addresses, and unusual ports. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
bing-search.js:161
Finding
Denial of Service Through Unbounded HTTP Response Buffering<![CDATA[ ## Vulnerability Details **File Location**: `bing-search.js:161-165` and `bing-search.js:178-182` **Vulnerability Type**: Uncontrolled Resource Consumption **Risk Level**: Medium ### Vulnerable Code ```js }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { // 提取标题 ``` The response is truncated only after the complete body has already been accumulated: ```js // 限制长度 text = text.substring(0, 8000); resolve({ title, content: text }); ``` ### Technical Analysis The webpage-fetching implementation appends every received response chunk to the `data` string without enforcing a maximum response size. The eventual `substring(0, 8000)` operation limits only the returned text; it does not limit the memory consumed while downloading and buffering the original response. The configured 15-second request timeout does not reliably mitigate this issue because a server may transmit a substantial amount of data within that period. Depending on Node.js timeout semantics and continued network activity, a slow or streaming response may also retain resources longer than expected. Repeated requests or a single sufficiently large response can cause excessive heap allocation, garbage-collection pressure, process instability, or termination due to memory exhaustion. ### Attack Path 1. An attacker controls or identifies an HTTP endpoint that returns a very large response body. 2. The attacker causes the Skill to fetch that endpoint. 3. The endpoint streams a large amount of data to the Skill. 4. Each chunk is appended to the in-memory `data` string without a byte limit. 5. Memory consumption grows even though the final output is intended to contain only 8,000 characters. 6. The Node.js process experiences degraded performance or terminates from memory exhaustion, disrupting the Skill and potentially other workloads sharing the process or host. ### Impact Assessment Exploitation can cause denial of service within the No ...[truncated 436 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Track the number of response bytes as chunks arrive. 2. Define a strict maximum response size appropriate for the 8,000-character output requirement. 3. Abort the request immediately with `req.destroy()` when the byte limit is exceeded. 4. Process response data as a stream rather than buffering the entire body whenever possible. 5. Check the `Content-Length` header and reject responses exceeding the limit, while still enforcing a streaming limit because the header may be missing or false. 6. Add a total request deadline independent of socket inactivity. 7. Limit concurrent fetch operations to prevent aggregate memory exhaustion. 8. Validate response content types and reject binary or otherwise unsupported content before buffering it. 9. Add tests using oversized, chunked, compressed, and indefinitely streaming responses. 10. If compressed responses are supported in the future, enforce limits on decompressed bytes to prevent decompression bombs. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The skill hard-codes use of a Chinese-language Bing endpoint and presents it as the default behavior without any user choice, opt-in, or warning about jurisdictional, localization, or privacy implications. This can expose user queries to a specific regional service and may bias search results, language handling, and content filtering in ways the user did not intend.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The code hard-codes use of the Chinese Bing endpoint (`cn.bing.com`) and sends an `Accept-Language: zh-CN,zh;q=0.9,en;q=0.8` header, while the file header also states it uses the Chinese Bing search engine. This imposes a specific language/locale behavior on all users without offering a choice or documenting opt-in, which matches the language/locale policy violation category.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The fetch command accepts an arbitrary user-supplied HTTP/HTTPS URL and retrieves it directly, which expands the skill from 'Bing Chinese search' into a general-purpose network fetcher. In an agent environment, this can enable SSRF-style access to internal or sensitive endpoints, metadata services, localhost services, or policy-bypassing direct web access that was not disclosed by the manifest.

Static analysis

No suspicious patterns detected.