Back to skill

Security audit

Docs Feeder

Security checks for vulnerabilities and agentic risk

Overview

This documentation-fetching skill is coherent, but needs review because it can load arbitrary remote content directly into an AI agent and fetch unrestricted URLs without strong safeguards.

Install only if you are comfortable with the agent fetching documentation from the network. Prefer known trusted project names or trusted HTTPS documentation URLs, avoid internal or private-network URLs, treat fetched text as untrusted reference material, and review content before letting an agent act on it or before using --save.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T01 · Skill Instruction Hijacking

Error
Location
fetch-docs.js:143
Finding

Untrusted Remote Documentation Can Inject Instructions into the Consuming AI Agent

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
fetch-docs.js:36
Finding

Arbitrary URL Fetching and Unrestricted Redirects Permit SSRF

Content
View full analysis
{ const client = url.startsWith('https') ? https : http; const req = client.get(url, { timeout: 30000 }, (res) => { // Handle redirects if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { if (maxRedirects <= 0) { reject(new Error('Too many redirects')); return; } const redirectUrl = new URL(res.headers.location, url).href; resolve(fetch(redirectUrl, maxRedirects - 1)); return; } if (res.statusCode !== 200) { reject(new Error(`HTTP ${res.statusCode}`)); return; } let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); ``` `fetch-docs.js:143-149` ```javascript if (input.match(/^https?:\/\//)) { projectName = input.replace(/^https?:\/\//, '').split('/')[0].replace(/^www\./, '').split('.')[0]; result = await fetchLlmsTxt(input); if (!result) { error(`无法从 ${input} 抓取文档`); } } ``` `fetch-docs.sh:69-96` ```bash fetch_llms_txt() { local base_url="$1" local llms_path="${2:-/llms-full.txt}" # Try llms-full.txt first local url="${base_url}${llms_path}" log "尝试 $url" local content if content=$(curl -sfL --max-time 30 "$url" 2>/dev/null); then if [[ -n "$content" && ${#content} -gt 100 ]]; then echo "$content" return 0 fi fi # Try llms.txt if [[ "$llms_path" == "/llms-full.txt" ]]; then url="${base_url}/llms.txt" log "尝试 $url" ...[truncated 2860 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
fetch-docs.js:49
Finding

Remote Responses Are Buffered Without an Enforced Size Limit

Content
View full analysis
data += chunk); res.on('end', () => resolve(data)); ``` `fetch-docs.js:205-210` ```javascript const { content, source } = result; const size = Buffer.byteLength(content, 'utf8'); if (size > MAX_SIZE) { warn(`文档较大 (${formatSize(size)}),可能需要裁剪`); } ``` `fetch-docs.sh:69-96` ```bash fetch_llms_txt() { local base_url="$1" local llms_path="${2:-/llms-full.txt}" # Try llms-full.txt first local url="${base_url}${llms_path}" log "尝试 $url" local content if content=$(curl -sfL --max-time 30 "$url" 2>/dev/null); then if [[ -n "$content" && ${#content} -gt 100 ]]; then echo "$content" return 0 fi fi # Try llms.txt if [[ "$llms_path" == "/llms-full.txt" ]]; then url="${base_url}/llms.txt" log "尝试 $url" if content=$(curl -sfL --max-time 30 "$url" 2>/dev/null); then if [[ -n "$content" && ${#content} -gt 100 ]]; then echo "$content" return 0 fi fi fi return 1 } ``` `fetch-docs.sh:197-201` ```bash # Check size local size=${#content} if [[ $size -gt $MAX_SIZE ]]; then warn "文档较大 ($(numfmt --to=iec $size)),可能需要裁剪" fi ``` ### Technical Analysis The declared 500 KB maximum is only a warning threshold. It is evaluated after the complete response has already been downloaded and stored in memory. In JavaScript, every received chunk is concatenated into a string until the server ends the response. In the shell implementation, command substitution captures the complete `curl` ...[truncated 1567 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (6)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly encourages fetching documentation from arbitrary URLs and optionally saving the retrieved content to disk, but it provides no warning about privacy, trust, or data-handling risks. This can expose the agent or user to untrusted remote content, accidental ingestion of sensitive/internal documentation, or persistence of malicious or confidential data in local files and agent context.

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 natural-language comments, log messages, errors, examples, and help text are predominantly in Chinese, with no option for users to select another language. This can violate a language/locale policy when tools are expected to respect user language preferences or provide opt-in localization.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This shell skill presents its description, usage examples, option help, and dependency error text in Chinese only. The policy allows locale constraints only when explicitly documented and justified or when the user is given a choice, neither of which is present here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The script performs network requests to user-supplied or registry-derived URLs and fetches arbitrary remote content without enforcing an allowlist, scheme/host restrictions, or content validation. In an agent context, this can expose the runtime to SSRF-style access to internal services or cause ingestion of attacker-controlled prompt content into downstream LLM workflows.

Content

Scanner excerpt · fetch-docs.sh (reported line 72)May include surrounding context.

sh
log "尝试 $url"
    
    local content
    if content=$(curl -sfL --max-time 30 "$url" 2>/dev/null); then
        if [[ -n "$content" && ${#content} -gt 100 ]]; then
            echo "$content"
            return 0

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The JSON comment string at L002 is written only in Chinese ("项目名 → 文档配置"), which imposes a specific language in the skill artifact without any visible opt-in, alternative locale, or justification. This matches the language/locale policy concern for natural-language content in config files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code performs a filesystem write when --save is used, but there is no user-facing warning in the usage text or inline comments describing where data will be written and that fetched remote content will be saved locally. Although the operation is optional, it is still a file write and the only disclosure comes after the write completes.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.