Back to skill

Security audit

GEO Site Readiness Audit

Security checks for vulnerabilities and agentic risk

Overview

The skill is a legitimate website audit tool, but it can make unvalidated requests to any user-supplied host, including internal network targets, so it should be reviewed before installation.

Install only if you are comfortable with the skill making outbound HTTP requests. Use it for domains you own or are authorized to test, avoid internal IPs or localhost targets, and run it in an environment with egress controls. Review the CI examples before copying them, especially quoting user-controlled variables.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/geo_audit.py:24
Finding
Unrestricted Server-Side Request Forgery Through User-Controlled Audit Targets<![CDATA[ ## Vulnerability Details **File Location**: `scripts/geo_audit.py:24-49` and `scripts/geo_audit.py:369-376` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Complete Vulnerable Code ```python def __init__(self, domain, timeout=10, delay=0, user_agent=None): self.domain = domain.replace('https://', '').replace('http://', '').rstrip('/') self.base_url = f"https://{self.domain}" self.timeout = timeout self.delay = delay self.results = { "site": self.domain, "timestamp": datetime.utcnow().isoformat() + "Z", "score": 0, "total": 29, "grade": "F", "dimensions": [] } self.headers = { 'User-Agent': user_agent or 'GEO-Audit-Bot/1.0 (Research Purpose)' } def fetch(self, path='', full_url=None): """Fetch a URL with error handling.""" url = full_url or urljoin(self.base_url, path) try: time.sleep(self.delay) resp = requests.get( url, headers=self.headers, timeout=self.timeout, allow_redirects=True ) return resp except Exception as e: return None ``` ```python def check_https(self): """Check 4.2: HTTPS enforced.""" try: http_resp = requests.get( f"http://{self.domain}", timeout=self.timeout, allow_redirects=False ) if http_resp.status_code in [301, 302] and 'https' in http_resp.headers.get('Location', ''): return {"check": "HTTPS enforced", "status": "pass", "notes": "HTTP redirects to HTTPS"} except: pass return {"check": "HTTPS enforced", "status": "pass", "notes": "Site uses HTTPS"} ``` ### Technical Analysis The command-line `domain` value is directly converted into HTTP and HTTPS request targets. The implementation does not validate the parsed hostname, port, resolved IP address, or URL authority before issuing requests. Consequently, ...[truncated 1948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse targets with `urllib.parse.urlsplit()` and accept only explicit `http` or `https` schemes. 2. Reject URLs containing user information, malformed authorities, fragments, or ports outside an approved policy. 3. Resolve all destination hostnames before connecting. 4. Reject every resolved IPv4 and IPv6 address that is loopback, private, link-local, multicast, reserved, unspecified, or otherwise non-global. 5. Explicitly block common cloud metadata destinations and hostnames. 6. Disable automatic redirects or validate the hostname and resolved addresses of every redirect destination before following it. 7. Defend against DNS rebinding by ensuring the validated address is the address used for the connection. 8. Apply outbound network firewall rules so the audit process cannot contact internal or metadata networks. 9. Add maximum response-size and redirect-count limits. 10. If the tool is exposed through an API, maintain an allowlist of auditable public domains and require authorization for every audit. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/integrations.md:15
Finding
Shell Command Injection in GitHub Actions Integration Example<![CDATA[ ## Vulnerability Details **File Location**: `references/integrations.md:15-18` **Vulnerability Type**: Shell Command Injection **Risk Level**: Medium ### Complete Vulnerable Code ```yaml - name: Run GEO Audit run: | python scripts/geo_audit.py ${{ vars.SITE_URL }} --output json > audit.json ``` ### Technical Analysis GitHub Actions evaluates `${{ ... }}` expressions before passing the resulting script to the command shell. The `SITE_URL` value is interpolated directly into shell source code without quoting. If an attacker can control or influence this variable, shell metacharacters, command substitutions, redirections, or command separators in the value will be interpreted by the runner shell rather than treated only as a URL argument. This is distinct from ordinary argument injection: direct expression interpolation changes the shell program itself before execution. ### Attack Path 1. A workflow adopts the documented GitHub Actions integration. 2. An attacker gains the ability to define or influence `vars.SITE_URL`, such as through an insufficiently protected repository or environment variable. 3. The attacker places shell syntax in the variable value. 4. GitHub Actions substitutes the value into the `run` script before shell execution. 5. The runner shell interprets the injected syntax and executes attacker-selected commands with the workflow job's permissions. ### Impact Assessment Successful exploitation provides command execution in the GitHub Actions runner. The resulting scope depends on workflow permissions and secret availability, but may include: - Reading files and generated artifacts in the runner workspace. - Modifying audit output or build artifacts. - Accessing environment variables available to the job. - Using the workflow's repository token within its configured permissions. - Exfiltrating secrets exposed to the affected workflow. - Modifying repository contents if the workflow token has write privileges. Exploitatio ...[truncated 112 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Pass the expression through the step environment and quote the shell expansion: ```yaml - name: Run GEO Audit env: SITE_URL: ${{ vars.SITE_URL }} run: | python scripts/geo_audit.py "$SITE_URL" --output json > audit.json ``` Additionally: 1. Validate `SITE_URL` as a public HTTP or HTTPS URL before using it. 2. Restrict who can modify repository and environment variables. 3. Use protected GitHub environments for security-sensitive configuration. 4. Apply least-privilege `permissions` settings to the workflow token. 5. Do not expose sensitive secrets to workflows that process attacker-influenced configuration. 6. Prefer argument-array execution in programmatic integrations where no shell is needed. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/geo_audit.py:10
Finding
Unpinned Third-Party Dependency Installation Guidance<![CDATA[ ## Vulnerability Details **File Location**: `scripts/geo_audit.py:10-14` **Vulnerability Type**: Uncontrolled Third-Party Dependency Resolution **Risk Level**: Low ### Complete Vulnerable Code ```python try: import requests except ImportError: print("Error: requests library required. Install with: pip install requests") sys.exit(1) ``` ### Technical Analysis When the `requests` package is unavailable, the script advises installing it without a version constraint, lock file, hash, or trusted-index requirement. Following `pip install requests` resolves whichever package version the configured package index currently considers appropriate. Although `requests` is a legitimate and widely used dependency, unconstrained installation makes the environment non-reproducible and leaves future dependency selection outside the reviewed project state. It also does not verify the integrity of the package artifact or its transitive dependencies. ### Attack Path 1. A user runs the audit script in an environment where `requests` is not installed. 2. The script displays the unconstrained installation command. 3. The user executes `pip install requests`. 4. `pip` resolves the package and transitive dependencies from the configured package index at installation time. 5. A compromised, malicious, or incompatible release available through that supply chain becomes part of the audit runtime. ### Impact Assessment If dependency resolution supplies a compromised package, its installation or import may execute code with the privileges of the user or automation account running the audit. Potential scope includes: - Access to files readable by the audit process. - Access to environment variables and CI credentials. - Modification of generated reports or workspace files. - Network communication using the host's outbound access. No malicious package source or dependency-confusion package is present in the reviewed repository. The finding concerns unsafe depend ...[truncated 98 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a dependency manifest with an audited version constraint, for example: ```text requests==<reviewed-version> ``` 2. Generate and commit a lock file containing exact transitive dependency versions. 3. Use hash-verified installation, such as `pip install --require-hashes -r requirements.txt`. 4. Configure automation to use an approved package index or internal mirror. 5. Run dependency vulnerability and provenance checks in CI. 6. Document supported Python and dependency versions. 7. Replace the runtime installation suggestion with a command referencing the project's locked dependency file. ]]>
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 (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documentation advertises executable scripts that perform network access and write output files, but it declares no explicit tool scope or permissions. In an agent environment, this can lead to overbroad execution where the skill is invoked with more capability than users or reviewers expect, increasing the chance of unintended external requests or local file modifications.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The description contains broad trigger phrases like 'use whenever the user mentions' several related topics, which can cause the skill to activate in contexts that do not require it. Over-triggering is risky because this skill performs website auditing actions, potentially causing unsolicited network access, scans of third-party domains, or report generation based on ambiguous user intent.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The docstring says this function checks whether core content is present in raw HTML, implying it analyzes the fetched response body. However, the code uses `html.lower()` even though no `html` variable exists, so it cannot perform the documented check and will fail at runtime rather than auditing page content.

Dynamic Request Target

Medium
Category
Server-Side Request Forgery
Content
def check_https(self):
        """Check 4.2: HTTPS enforced."""
        try:
            http_resp = requests.get(f"http://{self.domain}", timeout=self.timeout, allow_redirects=False)
            if http_resp.status_code in [301, 302] and 'https' in http_resp.headers.get('Location', ''):
                return {"check": "HTTPS enforced", "status": "pass", "notes": "HTTP redirects to HTTPS"}
        except:
Confidence
95% confidence
Finding
The script performs HTTP requests to a fully user-controlled target (`self.domain`) without validation, allowing the runtime environment to be used as a network proxy to reach arbitrary hosts. In an agent or server context, an attacker could target internal IPs, localhost, cloud metadata endpoints, or other restricted services, turning a GEO audit into an SSRF primitive.

Missing User Warnings

Low
Confidence
90% confidence
Finding
This code performs HTTP requests to the target domain provided by the user, which is a network operation covered by the missing-warning rule for code files. Although the script's purpose is auditing websites, the code itself provides no confirmation prompt or user-facing disclosure at the point of access about contacting external systems and transmitting headers such as the User-Agent.