T09 · Insecure Skill Coding Practices
- Location
server/search.js:13- Finding
Unauthenticated Remote Command Injection Through Search Query
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a search service, but its bundled server code can let unauthenticated users run commands, browse internal network URLs, and view shared search history.
Do not run this as a public or trusted service until it is patched. At minimum, replace shell-based search execution with argument-based process calls, remove or strictly validate arbitrary URL extraction, remove public shared history, sanitize frontend rendering, disclose query transmission and retention, regenerate dependencies from HTTPS sources, and test only in an isolated environment with no secrets or internal-network access.
server/search.js:13Unauthenticated Remote Command Injection Through Search Query
server-v2.js:226Unrestricted Server-Side Request Forgery in Content Extraction Endpoint
public/index.html:482DOM-Based Cross-Site Scripting Through Unescaped Search Results
${api.description}
server-v2.js:360Unauthenticated Disclosure of Shared User Search History
package-lock.json:15Dependency Lockfile Uses Plaintext HTTP Package Sources
basic-ftp 5.2.0 is flagged with command-injection and denial-of-service advisories. In this lockfile it appears as a transitive dependency via get-uri/proxy handling rather than an explicitly chosen package, so exploitation depends on whether the application actually processes attacker-controlled FTP or proxy URIs, but the vulnerable code is present in the dependency graph.
extract-zip 2.0.1 is associated with arbitrary file write and symlink traversal issues during archive extraction. Since Puppeteer’s browser-management stack uses archive download/extraction, a malicious or tampered browser archive could potentially write outside the intended directory and compromise the host environment.
ip-address 10.1.0 has reported issues involving parsing inconsistencies and XSS in HTML-emitting methods. In this dependency graph it is transitively used by SOCKS/proxy components, so the practical risk is limited unless the application exposes these parsing results or HTML-rendering methods to attacker-controlled input.
js-yaml 4.1.1 is flagged for CPU-exhaustion issues when parsing malicious YAML constructs. As a transitive dependency of cosmiconfig used by Puppeteer, it becomes relevant if the application loads attacker-influenced configuration files or scans untrusted directories for config.
path-to-regexp 8.3.0 is reported vulnerable to ReDoS/DoS patterns, and it is used by router/express to compile route definitions. If the application defines complex vulnerable route patterns or allows dynamic route creation, attackers may be able to trigger excessive CPU consumption via crafted paths against a network-exposed Express service.
ws 8.19.0 is flagged for memory disclosure and memory exhaustion issues. Because ws is used by puppeteer-core for browser protocol communication, risk is highest when the skill connects to untrusted WebSocket endpoints or exposes browser-automation channels across trust boundaries.
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<button onclick="doSearch()" data-i18n="search">搜索</button>
</div>
<!-- 搜索结果展示 -->
<div id="searchResults" style="max-width: 700px; margin: 20px auto; text-align: left;"></div>
<div class="api-demo">
The code builds a shell command with unsanitized user-controlled input via execSync(skillhub search "${query}"). Quoting with double quotes is not sufficient to prevent shell metacharacter expansion or command substitution, so an attacker may execute arbitrary local commands under the server's privileges.
The skill explicitly instructs users or agents to send search queries to a third-party remote API, but it does not warn that prompts, keywords, or potentially sensitive user data will leave the local environment. In an agent context, search terms may contain proprietary, personal, or operationally sensitive information, so undisclosed external transmission creates a real privacy and data-governance risk.
The hardcoded remote endpoint indicates reliance on an external hosted service rather than a purely local capability. This increases exposure because agents may automatically contact the remote domain and disclose operational metadata or search content without an explicit trust decision by the user.
curl -X POST https://api.claw-search.com/api/search \
-H "Content-Type: application/json" \
-d '{"query": "openclaw ai agent", "count": 10}'
The hardcoded remote endpoint indicates reliance on an external hosted service rather than a purely local capability. This increases exposure because agents may automatically contact the remote domain and disclose operational metadata or search content without an explicit trust decision by the user.
curl -X POST https://api.claw-search.com/api/search \
-H "Content-Type: application/json" \
-d '{"query": "openclaw ai agent", "count": 10}'
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
docker-compose up -d
# 测试
curl https://api.claw-search.com/health
```
### 手动部署
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
docker-compose up -d
# 测试
curl https://api.claw-search.com/health
```
### 手动部署
The skill description advertises web search and URL content extraction but does not clearly warn users that queries and fetched URLs will be transmitted to external services over the network. For an agent skill, this omission can cause users or downstream agents to unknowingly send sensitive prompts, internal URLs, or proprietary data to third parties, creating privacy and data-governance risk.
This JSON file contains multiple natural-language fields in Chinese, including descriptions and tags, while other fields remain in English. Because the file does not document that the skill is intentionally Chinese-language or offer any locale choice, it effectively imposes a language preference without user opt-in.
The lockfile pins package tarball downloads to plain HTTP mirror URLs, which permits man-in-the-middle tampering of package contents during installation. While integrity hashes help detect some tampering, relying on insecure transport for dependency retrieval materially increases supply-chain risk and can enable build disruption or compromised installs if integrity checks are bypassed or alternate tooling ignores them.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
<div id="searchResults" style="max-width: 700px; margin: 20px auto; text-align: left;"></div>
<div class="api-demo">
<h3 data-i18n="curl_demo">cURL 示例</h3>
<pre><span class="keyword">curl</span> -X POST https://api.claw-search.com/api/search \
-H <span class="string">"Content-Type: application/json"</span> \
-d '<span class="string">{"query": "openclaw ai agent", "count": 10}</span>'</pre>
The natural-language strings describe automatic language switching based on IP, and the initialization logic defaults the experience based on detected locale rather than explicit user choice. This can violate language/locale policy because the skill applies a locale decision automatically instead of requiring opt-in, even though a manual selector exists.
The English translation explicitly states that language is auto-detected from IP, and the page initializes language based on detected locale instead of explicit user choice. This is a natural-language locale-policy concern because the skill imposes locale behavior automatically rather than making it opt-in.
The Japanese translation says the language is automatically detected from IP, which is locale-based behavior applied without explicit opt-in. That natural-language instruction conflicts with the requirement to avoid forcing or inferring language/locale unless the user chooses it or the constraint is clearly justified.
The Korean translation also states that language is detected based on IP, indicating automatic locale selection without user opt-in. This is a policy issue in natural-language content because locale behavior is imposed by inference rather than explicit selection.
This duplicate detection corresponds to the same fetch call that transmits search queries to the external API. The danger is contextual: the app is a search frontend, so off-site transmission is expected, but lack of user warning and possible sensitive queries make it a real privacy issue.
const resultsDiv = document.getElementById('searchResults');
resultsDiv.innerHTML = '<div style="text-align:center;padding:20px;">🔍 搜索中...</div>';
fetch('https://api.claw-search.com/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query, count: 5 })
This duplicate detection corresponds to the same fetch call that transmits search queries to the external API. The danger is contextual: the app is a search frontend, so off-site transmission is expected, but lack of user warning and possible sensitive queries make it a real privacy issue.
const resultsDiv = document.getElementById('searchResults');
resultsDiv.innerHTML = '<div style="text-align:center;padding:20px;">🔍 搜索中...</div>';
fetch('https://api.claw-search.com/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query, count: 5 })
User-entered search terms are transmitted to a third-party API endpoint without any visible privacy notice, consent prompt, or data-use disclosure. Search queries can contain sensitive personal, business, or authentication-related information, so silent transmission creates a real privacy risk even if the transport is HTTPS.
Detected: suspicious.dangerous_exec, suspicious.env_credential_access