Back to skill

Security audit

media-crawler-local

Security checks for vulnerabilities and agentic risk

Overview

This local media crawler helper is mostly purpose-aligned, but it needs review because it can send cookies and arbitrary MCP arguments to a service endpoint chosen by command-line input or environment variable.

Install only if you intend to use a local media-crawler service and understand that crawl targets, keywords, task IDs, and optional platform cookies will be sent to that service. Keep BIL_CRAWL_URL pointed at a trusted localhost endpoint unless you deliberately trust a remote HTTPS service, and avoid passing browser cookies through command-line history or to any endpoint you do not control.

Vulnerability Patterns
  • 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
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_tool.mjs:8
Finding

Unrestricted Service Endpoint Override Can Expose Sensitive MCP Arguments

Content
View full analysis
[args_json] [base_url]"); print_error( 'Example: node mcp_tool.mjs list_archives \'{"platform":"bilibili","limit":10}\'' ); process.exit(2); } let args; try { args = JSON.parse(argsRaw); if (typeof args !== "object" || Array.isArray(args) || args === null) throw new Error(); } catch { print_error("args_json must be a valid JSON object"); process.exit(2); } const mcpUrl = `${baseUrl}/mcp`; try { await fetch(`${baseUrl}/`, { signal: AbortSignal.timeout(3000) }); } catch { print_error(`Service not reachable at ${baseUrl}`); process.exit(1); } const headers = { "Content-Type": "application/json", Accept: "application/json, text/event-stream" }; const initPayload = { jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "media-crawler-local", version: "1.0.0" } }, }; const callPayload = { jsonrpc: "2.0", id: 2, method: "tools/call", params: { name: toolName, arguments: args }, }; // Initialize session (best-effort) try { await fetch(mcpUrl, { method: "POST", headers, body: JSON.stringify(initPayload), signal: AbortSignal.timeout(5000) }); } catch {} const res = await fetch(mcpUrl, { method: "POST", headers, body: JSON.stringify(callPayload), signal: AbortSignal.timeout(30000), }); ``` The shell implementation has the same endpoint-selection behavior: ```bash BASE_URL="${3:-${BIL_CRAWL_URL:-http:/ ...[truncated 2412 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/mcp_tool.mjs:8
Finding

Generic MCP Client Allows Invocation of Undeclared Tools

Content
View full analysis
[args_json] [base_url]"); print_error( 'Example: node mcp_tool.mjs list_archives \'{"platform":"bilibili","limit":10}\'' ); process.exit(2); } let args; try { args = JSON.parse(argsRaw); if (typeof args !== "object" || Array.isArray(args) || args === null) throw new Error(); } catch { print_error("args_json must be a valid JSON object"); process.exit(2); } const mcpUrl = `${baseUrl}/mcp`; const callPayload = { jsonrpc: "2.0", id: 2, method: "tools/call", params: { name: toolName, arguments: args }, }; const res = await fetch(mcpUrl, { method: "POST", headers, body: JSON.stringify(callPayload), signal: AbortSignal.timeout(30000), }); ``` The shell implementation similarly places an unrestricted tool name into the request: ```bash TOOL_NAME="${1:-}" call_payload=$(TOOL_NAME_ENV="$TOOL_NAME" ARGS_FILE_ENV="$tmp_args_file" node -e ' const fs = require("node:fs"); const tool = process.env.TOOL_NAME_ENV || ""; const file = process.env.ARGS_FILE_ENV || ""; const raw = (file && fs.existsSync(file)) ? fs.readFileSync(file, "utf8") : "{}"; let args={}; try { args=JSON.parse(raw); } catch (e) { console.error("Invalid args_json, must be valid JSON object"); process.exit(2); } if (typeof args !== "object" || Array.isArray(args) || args===null) { console.error("args_json must be a JSON object"); process.exit(2); } process.stdout.write(JSON.stringify({jsonrpc:"2.0",id:2,method:"tools/call",params:{name:tool,arguments:args}})); ') curl -sS -N "$MCP_URL" \ -H 'Ac ...[truncated 2409 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (12)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to use shell, network, and environment-derived configuration (e.g. BIL_CRAWL_URL) but does not declare any tool scope or allowed-tools boundaries. That increases the blast radius because an agent may execute shell commands and send HTTP requests without explicit least-privilege constraints, making misuse or prompt-injection-driven abuse easier.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill explicitly supports passing browser-derived cookies and sending them to a local HTTP service, but it does not require an explicit user warning or consent flow about handling sensitive session data. Even though the endpoint is localhost, cookies can grant authenticated access and may be logged, stored, or misrouted if the local service is compromised or the base URL is overridden.

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 · SKILL.md (reported line 135)May include surrounding context.

Invoke-RestMethod -Uri "http://127.0.0.1:39002/mcp" -Method POST -ContentType "application/json" -Headers @{Accept="application/json, text/event-stream"} -Body $body | ConvertTo-Json -Depth 10

text

### macOS / Linux(curl 系统自带)

**REST 搜集:**
```bash

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code performs an HTTP POST to a crawl service using a user-supplied URL embedded in the endpoint path, but there is no confirmation prompt or user-facing disclosure at the point of transmission. The brief Chinese header describes usage but does not warn that the provided URL will be sent to a local or environment-configured service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/crawl.sh (reported line 31)May include surrounding context.

sh
exit 1
}

curl -fsS -X POST "$endpoint" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data "$payload"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The only natural-language description and usage text in the file are written in Chinese, which imposes a specific language on users without opt-in or explanation. Under the policy rule, locale or language constraints should either be optional for users or clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code sends the user-supplied arguments object to a network endpoint via fetch, which may transmit user or system data to the MCP service. While the operation is visible in code, there is no confirmation prompt, user-facing notice, or explanatory comment/docstring disclosing that arguments are sent over HTTP.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/mcp_tool.sh (reported line 46)May include surrounding context.

sh
process.stdout.write(JSON.stringify({jsonrpc:"2.0",id:2,method:"tools/call",params:{name:tool,arguments:args}}));
')

curl -sS -N "$MCP_URL" \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Content-Type: application/json' \
  --data "$init_payload" >/dev/null

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This shell script sends initialization data and the user-supplied JSON arguments to an HTTP endpoint via curl, which can transmit user or system data over the network. While the script checks reachability and validates JSON, it does not provide a user-facing warning, confirmation, or explanatory comment about this network transmission.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file includes natural-language documentation in Chinese only, which imposes a specific language on users without any opt-in or stated locale restriction. Under the policy, forcing a language without user choice can be a natural-language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script invokes another Node.js program via execFileSync, which is a subprocess operation covered by the missing-warning rule for code files. While the file has a brief usage header, it does not clearly disclose to a user that running this script will execute a child process, and there is no confirmation prompt or visible log message at the call site.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The top-of-file description and usage guidance are written in Chinese, which effectively fixes the interaction/documentation language for users of this skill. Under the stated policy, language-specific behavior should offer a choice or clearly justified constraint, neither of which appears here.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/crawl_mcp.mjs:34

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/list_archives_mcp.mjs:28