Back to skill

Security audit

SEO Analyzer by G0atbot

Security checks for vulnerabilities and agentic risk

Overview

This SEO skill is mostly purpose-aligned, but its bundled analyzer can fetch arbitrary URLs from the host running it, including internal or metadata endpoints.

Review before installing if your agent runs inside a private network or cloud environment. Use it only for public websites, and prefer network egress controls or code changes that block loopback, private, link-local, and metadata addresses and cap response size.

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

T09 · Insecure Skill Coding Practices

Error
Location
seo-analyzer.js:26
Finding
Unrestricted Server-Side URL Fetching Enables SSRF<![CDATA[ ## Vulnerability Details **File Location**: `seo-analyzer.js:26-48`, with user-controlled invocation at `seo-analyzer.js:235-248` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```js function fetchPage(url) { return new Promise((resolve, reject) => { const parsedUrl = new URL(url); const client = parsedUrl.protocol === 'https:' ? https : http; const options = { hostname: parsedUrl.hostname, path: parsedUrl.pathname + parsedUrl.search, method: 'GET', headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEO-Analyzer/1.0)' }, timeout: 10000 }; const req = client.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); req.on('error', reject); req.on('timeout', () => reject(new Error('Request timeout'))); req.end(); }); } ``` The request target originates directly from the command-line argument: ```js async function main() { const url = process.argv[2]; if (!url) { console.log('Usage: node seo-analyzer.js <url>'); console.log('Example: node seo-analyzer.js https://example.com'); process.exit(1); } // Add protocol if missing const fullUrl = url.match(/^https?:\/\//) ? url : `https://${url}`; try { log(colors.blue, `🔍 Analyzing ${fullUrl}...`); const html = await fetchPage(fullUrl); const results = analyzeHTML(html, fullUrl); printResults(results); } catch (error) { log(colors.red, `Error: ${error.message}`); process.exit(1); } } ``` ### Technical Analysis The command-line argument controls the hostname, port through the parsed URL, request path, query string, and whether the request uses HTTP or HTTPS. The application performs the request from its own network context without applying: - An approved-host allowlist. - Public-address validation. - DNS resolution and resolve ...[truncated 2624 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Restrict destination protocols** - Explicitly permit only `http:` and `https:`. - Reject URLs containing unsupported schemes or malformed authority components. 2. **Resolve and validate every destination** - Resolve the hostname before connecting. - Reject all loopback, private, link-local, multicast, unspecified, reserved, and documentation address ranges. - Apply equivalent validation to IPv4, IPv6, and IPv4-mapped IPv6 addresses. - Explicitly block known cloud metadata addresses, including `169.254.169.254`. 3. **Prevent DNS rebinding** - Validate every resolved address, not only the hostname string. - Connect only to a validated resolved address while preserving the intended hostname for TLS verification. - Re-resolve and revalidate the destination for every new connection. 4. **Control redirects** - If redirect support is added, apply the same protocol, hostname, and resolved-IP validation to every redirect target. - Set a small maximum redirect count. 5. **Prefer an allowlist or controlled egress proxy** - Where operationally possible, limit requests to explicitly approved public domains. - Route requests through an egress proxy that enforces destination and address-range policies. - Apply network firewall rules preventing the process from reaching metadata endpoints and internal management networks. 6. **Limit response resources** - Set a strict maximum response-body size. - Abort and destroy the request when the limit is exceeded. - Validate response content types before processing. - On timeout, call `req.destroy()` rather than only rejecting the promise. 7. **Add regression tests** - Verify rejection of loopback, RFC 1918, link-local, IPv6-local, metadata, alternative numeric IP notation, and DNS-rebinding cases. - Verify that ordinary public HTTP and HTTPS destinations remain functional. ]]>
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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.