Back to skill

Security audit

SEO Audit Bot

Security checks for vulnerabilities and agentic risk

Overview

This SEO skill is mostly purpose-aligned, but it can fetch arbitrary URLs through curl without public-URL safeguards and stores responses in predictable temporary files.

Review before installing. Use it only against public websites you intend to audit, avoid localhost/private/internal URLs, and do not run the bundled script with elevated privileges. A safer version should restrict targets to public http/https URLs, validate redirects, use private temporary files, set request limits, clean up after itself, and escape remote text before displaying it.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/audit.sh:6
Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/audit.sh`, lines 6-18 and 74-86 **Vulnerability Type**: Server-Side Request Forgery (SSRF) through unrestricted outbound requests **Risk Level**: High ### Vulnerable Code ```bash URL=$1 if [ -z "$URL" ]; then echo "Usage: ./audit.sh <url>" exit 1 fi echo "=== SEO AUDIT: $URL ===" echo "" # Fetch main page echo "--- MAIN PAGE ---" HTTP_CODE=$(curl -s -o /tmp/seo_page.html -w "%{http_code}" -L "$URL" 2>/dev/null) ``` Additional requests are constructed from the same unvalidated input: ```bash echo "--- ROBOTS.TXT ---" ROBOTS_CODE=$(curl -s -o /tmp/seo_robots.txt -w "%{http_code}" "$URL/robots.txt" 2>/dev/null) echo "--- SITEMAP.XML ---" SITEMAP_CODE=$(curl -s -o /tmp/seo_sitemap.xml -w "%{http_code}" "$URL/sitemap.xml" 2>/dev/null) ``` ### Technical Analysis The script accepts an arbitrary URL as its first argument and passes it directly to `curl`. It does not enforce an `http` or `https` scheme, validate the destination hostname, resolve and inspect destination IP addresses, or reject loopback, private, link-local, reserved, and cloud metadata addresses. The main-page request also uses `curl -L`, which follows redirects. Even if an initial public hostname were trusted, that hostname could redirect the request to an internal address. The destination of each redirect is not revalidated. The downloaded main-page response is parsed and selected values are printed. All fetched responses are also saved to predictable files under `/tmp`. Therefore, the issue can be used for internal network probing and potentially for accessing services that trust requests originating from the host running the skill. ### Attack Path 1. An attacker supplies a URL pointing to an internal service, loopback interface, link-local service, or an attacker-controlled public endpoint. 2. The script passes that URL directly to `curl`. 3. Alternatively, the public endpoint returns a redirect to an internal destination ...[truncated 1212 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the URL with a dedicated URL parser rather than relying on shell string operations. 2. Permit only explicitly required schemes, preferably `https`; reject `file`, `ftp`, `gopher`, and all other protocols. 3. Require a valid hostname and reject URLs containing unexpected credentials or malformed authority components. 4. Resolve all destination hostnames and reject every address in loopback, private, link-local, multicast, reserved, and cloud metadata ranges for both IPv4 and IPv6. 5. Disable redirects or validate the scheme, hostname, and resolved IP address at every redirect hop. 6. Add strict request limits, such as: - `--connect-timeout` - `--max-time` - `--max-redirs` - A maximum response size 7. Run requests through an egress-restricted proxy or isolated fetch service that cannot access internal networks. 8. If arbitrary public websites are required, consider hostname allowlisting or require explicit administrator approval for destinations outside an established policy. 9. Do not rely on DNS validation performed only once, because DNS rebinding can change the resolved address between validation and connection. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/audit.sh:18
Finding
Predictable Shared Temporary Files Permit Symlink-Based File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/audit.sh`, lines 18, 76, and 86 **Vulnerability Type**: Insecure temporary-file handling and symlink overwrite **Risk Level**: Medium ### Vulnerable Code ```bash HTTP_CODE=$(curl -s -o /tmp/seo_page.html -w "%{http_code}" -L "$URL" 2>/dev/null) ``` ```bash ROBOTS_CODE=$(curl -s -o /tmp/seo_robots.txt -w "%{http_code}" "$URL/robots.txt" 2>/dev/null) ``` ```bash SITEMAP_CODE=$(curl -s -o /tmp/seo_sitemap.xml -w "%{http_code}" "$URL/sitemap.xml" 2>/dev/null) ``` ### Technical Analysis The script writes remote responses to fixed filenames in the globally shared `/tmp` directory. It does not securely create these files, verify file ownership, reject symbolic links, isolate files by user or process, or clean them up after execution. On systems where another local user can create entries in `/tmp`, an attacker can create one of these paths as a symbolic link to another file writable by the account running the audit. When `curl -o` opens the path, it can follow the symbolic link and truncate or replace the linked target with downloaded content. The fixed names also introduce a race condition between simultaneous audits. One process can overwrite a response while another process is parsing it, causing cross-run contamination and unreliable output. ### Attack Path 1. A local attacker predicts one of the fixed paths, such as `/tmp/seo_page.html`. 2. The attacker removes or waits for the path to be absent and creates a symbolic link from it to a file writable by the audit process. 3. A user or service runs `scripts/audit.sh`. 4. `curl -o /tmp/seo_page.html` follows the symbolic link. 5. The linked target is truncated or overwritten with content obtained from the supplied URL. 6. If concurrent audits are used instead, one audit can overwrite another audit's response before parsing completes, potentially exposing or corrupting data between runs. ### Impact Assessment Successful exploitation can overwri ...[truncated 654 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create a private temporary directory and remove it reliably: ```bash #!/bin/bash set -euo pipefail umask 077 TMP_DIR=$(mktemp -d) || exit 1 trap 'rm -rf -- "$TMP_DIR"' EXIT INT TERM PAGE_FILE="$TMP_DIR/page.html" ROBOTS_FILE="$TMP_DIR/robots.txt" SITEMAP_FILE="$TMP_DIR/sitemap.xml" ``` Then pass these private paths to `curl`: ```bash curl -s -o "$PAGE_FILE" ... curl -s -o "$ROBOTS_FILE" ... curl -s -o "$SITEMAP_FILE" ... ``` Additional hardening should include: 1. Never run the audit script with elevated privileges unless strictly necessary. 2. Set `umask 077` so downloaded responses are accessible only to the current user. 3. Use separate temporary directories for every invocation. 4. Install cleanup traps for normal exit and common termination signals. 5. Avoid reusing files across requests or concurrent audit runs. 6. Apply response-size limits to prevent remote servers from exhausting temporary storage. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/audit.sh:75
Finding
Unescaped Remote Content Can Inject Terminal Control Sequences<![CDATA[ ## Vulnerability Details **File Location**: `scripts/audit.sh`, lines 75-82 **Vulnerability Type**: Terminal escape-sequence injection through untrusted output **Risk Level**: Medium ### Vulnerable Code ```bash echo "--- ROBOTS.TXT ---" ROBOTS_CODE=$(curl -s -o /tmp/seo_robots.txt -w "%{http_code}" "$URL/robots.txt" 2>/dev/null) if [ "$ROBOTS_CODE" = "200" ]; then echo "Status: ✅ Found" cat /tmp/seo_robots.txt | head -20 else echo "Status: ❌ Not found (HTTP $ROBOTS_CODE)" fi ``` ### Technical Analysis The contents of `robots.txt` are controlled by the audited website. The script prints the first 20 lines directly to the terminal without filtering control bytes or escaping non-printable characters. A malicious `robots.txt` response can contain ANSI or other terminal control sequences. When displayed in a compatible terminal, these sequences may alter colors, move the cursor, erase or rewrite visible output, set terminal titles, create misleading hyperlinks, or invoke implementation-specific terminal features. Limiting output to 20 lines does not prevent the attack because a control sequence can fit in a single line. The same untrusted output may also be captured by log-processing systems, where control characters can make audit records misleading or difficult to review. ### Attack Path 1. An attacker hosts a website with a crafted `/robots.txt` response. 2. The response returns HTTP status 200 and includes terminal escape sequences within its first 20 lines. 3. A victim runs the audit against the attacker's URL. 4. The script downloads the response to `/tmp/seo_robots.txt`. 5. `cat /tmp/seo_robots.txt | head -20` writes the bytes directly to the terminal. 6. The terminal interprets supported control sequences, potentially altering the displayed audit output or terminal state. ### Impact Assessment The primary impact is integrity loss in the user interface and audit logs. An attacker may: - Hide or visually rewrite security-relevant outp ...[truncated 539 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never print raw remote bytes directly to an interactive terminal. 2. Strip or visibly encode control characters before display. 3. Preserve normal printable text and safe whitespace while escaping all other bytes. 4. Apply both line and byte limits because line limits alone do not restrict very long input. 5. Clearly delimit remote content so users can distinguish it from trusted script output. 6. Store raw content only in a private temporary file if it is needed for analysis. For example, render non-printable characters in an escaped representation rather than passing them through unchanged: ```bash head -n 20 "$ROBOTS_FILE" | LC_ALL=C sed -n 'l' | head -c 8192 printf '\n' ``` A more robust implementation should use a language or utility that explicitly permits only safe printable Unicode or ASCII characters and converts all control bytes into visible `\xNN` notation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code is SEO-related and broadly aligned with the stated domain, but the declared description significantly overstates what it does. The script performs a lightweight, single-URL scrape using curl/grep and reports basic page, robots.txt, and sitemap.xml indicators. It does not implement performance testing, comprehensive technical/content analysis, scoring, recommendations, or two-site comparison. Therefore the description does not accurately represent the actual behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The activation guidance says to use the skill when someone asks to "audit, analyze, or check the SEO of a website," which is a wide set of natural phrases without clear constraints or exclusion conditions. This ambiguity could cause unintended invocation for general website analysis requests that are not specifically intended to run this full SEO audit workflow.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill instructs the agent to fetch arbitrary user-supplied URLs and related paths like `robots.txt` and `sitemap.xml` without any user-facing warning or validation constraints. This creates SSRF-style risk and privacy concerns because the agent may be induced to contact internal, local, or sensitive network endpoints, or transmit metadata to unintended destinations under the guise of an SEO audit.

Missing User Warnings

Low
Confidence
92% confidence
Finding
The script downloads the target page to /tmp/seo_page.html, which is a file write and a network operation. While the script comments describe fetching SEO signals, there is no explicit user-facing warning that remote content will be retrieved and saved locally to /tmp.

Missing User Warnings

Low
Confidence
90% confidence
Finding
The script performs further HTTP requests for robots.txt and sitemap.xml and writes the responses to temporary files. These actions are not accompanied by a clear user-facing notice that multiple remote resources will be requested and stored locally.

Static analysis

No suspicious patterns detected.