Back to skill

Security audit

GEO Competitor Scanner

Security checks for vulnerabilities and agentic risk

Overview

This is a legitimate competitor-website scanner, but it can make unrestricted network requests to user-supplied targets and should be reviewed before use.

Install only if you are comfortable with a local script making outbound requests to every domain you provide. Use it with explicit public competitor domains only, avoid inputs from untrusted text, run it in a restricted environment, and prefer pinned dependency installation before executing the scanner.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scan_competitors.py:21
Finding
Unrestricted Request Destinations Enable Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/scan_competitors.py`, lines 21-40 and 259-265 **Vulnerability Type**: Server-Side Request Forgery through unrestricted user-controlled domains and redirects **Risk Level**: High **Vulnerable Code**: ```python class GEOScanner: """Scan website for GEO signals.""" def __init__(self, domain, timeout=10): self.domain = domain.replace('https://', '').replace('http://', '').rstrip('/') self.base_url = f"https://{self.domain}" self.timeout = timeout self.results = { 'domain': self.domain, 'technical': {}, 'content': {}, 'entity': {}, 'citation': {} } def fetch(self, path=''): """Fetch URL.""" url = urljoin(self.base_url, path) try: resp = requests.get(url, timeout=self.timeout, allow_redirects=True) return resp except Exception as e: return None ``` ```python domains = [args.brand] + [c.strip() for c in args.competitors.split(",")] results = [] for domain in domains: scanner = GEOScanner(domain) result = scanner.run_full_scan() results.append(result) ``` ### Technical Analysis Values supplied through `--brand` and `--competitors` are directly converted into outbound HTTPS request targets. The code does not validate that a supplied hostname resolves to a publicly routable address. It therefore permits loopback, private, link-local, reserved, and internal DNS destinations. The request also uses `allow_redirects=True`. Even if an initial hostname were validated as public, an attacker-controlled public endpoint could redirect the scanner to an internal address. No validation is performed for redirect destinations or after DNS resolution. The scanner sends requests to numerous fixed paths, including `/`, `/llms.txt`, `/robots.txt`, ` ...[truncated 1719 chars]
Remediation
## Remediation Suggestions 1. Parse targets using `urllib.parse` rather than modifying strings with `replace()`. 2. Accept only well-formed hostnames with an explicitly permitted scheme, preferably HTTPS. 3. Resolve every hostname before connecting and reject all loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses using Python's `ipaddress` module. 4. Disable automatic redirects or validate the hostname and resolved addresses of every redirect destination before following it. 5. Guard against DNS rebinding by ensuring the address used for the connection remains within the validated set. 6. Apply an outbound firewall or proxy allowlist so the scanner can reach only public web destinations. 7. Reject embedded credentials, unexpected ports, malformed hostnames, and ambiguous URL syntax. 8. Add tests covering loopback addresses, RFC 1918 networks, IPv6 local addresses, internal DNS names, encoded IP representations, and public-to-private redirects. 9. Return a clear validation error instead of silently treating blocked destinations as failed scans.

T08 · Insecure Dependencies

Warning
Location
scripts/scan_competitors.py:10
Finding
Unpinned Third-Party Dependency Installation Guidance## Vulnerability Details **File Location**: `scripts/scan_competitors.py`, lines 10-16 **Vulnerability Type**: Unsafe dependency acquisition without version or integrity constraints **Risk Level**: Medium **Vulnerable Code**: ```python try: import requests from bs4 import BeautifulSoup except ImportError: print("Error: pip install requests beautifulsoup4") sys.exit(1) ``` ### Technical Analysis When dependencies are unavailable, the script instructs the operator to install `requests` and `beautifulsoup4` without exact versions, cryptographic hashes, a lockfile, or a specified trusted package index. As a result, the command resolves mutable package releases from the environment's configured Python package repository at installation time. The project does not provide a requirements file or other reviewed dependency manifest that would make installations reproducible and integrity-checked. Although the package names shown are established package names and no malicious dependency is embedded in the project, the installation process remains exposed to compromised future releases, repository or mirror compromise, unsafe index configuration, and unreviewed breaking changes. ### Attack Path 1. The scanner is executed in an environment where one or both dependencies are missing. 2. The script prints the unpinned installation command. 3. A user or Agent runs that command using its configured package index. 4. Package resolution selects the latest matching releases without checking project-approved versions or hashes. 5. If a selected package, package release, index, or mirror has been compromised, attacker-controlled installation or runtime code executes locally. 6. That code receives the privileges and environment access of the user performing the installation or running the scanner. ### Impact Assessment Successful supply-chain exploitation could execute code with the privileges of the installin ...[truncated 384 chars]
Remediation
## Remediation Suggestions 1. Add a reviewed dependency manifest with exact versions for all direct and transitive dependencies. 2. Include cryptographic hashes and install with a command such as: ```bash python -m pip install --require-hashes -r requirements.txt ``` 3. Generate and maintain a lockfile using a dependency-management tool that supports reproducible resolution. 4. Configure installations to use an explicitly trusted package index and authenticated internal mirror where appropriate. 5. Review dependency updates through a controlled change process rather than resolving unrestricted latest versions at runtime. 6. Run software composition analysis and vulnerability checks against the locked dependency set. 7. Prefer installation in an isolated virtual environment with minimal filesystem, credential, and network privileges. 8. Replace the generic installation message with a reference to the project's locked installation procedure.
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs users to run local Python scripts that perform network access against competitor domains and write reports/results to disk, but the manifest declares no explicit tool scope or permission boundaries. In an agent environment, this mismatch can cause overbroad or implicit access, making it harder to enforce least privilege and increasing the risk of unintended network targeting or file writes.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The description uses very broad triggers like 'whenever the user mentions scanning competitor GEO strategies' and related competitor-analysis phrasing, which could cause the skill to activate for ordinary marketing or research requests without the user intending network scans. Because this skill can lead to external site access and file generation, overbroad invocation increases the chance of unexpected data collection or actions being taken in the wrong context.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest describes analyzing competitor GEO strategies, AI citation signals, and benchmarking performance, which implies substantive comparative analysis of how competitors win citations. In practice, the citation scan just checks whether a few fixed paths like /compare, /about, and /what-is return a response, and the rest of the scan relies on basic counts from homepage structure and schema extraction.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The reporting function formats raw scan outputs into a markdown table and score summary, but it does not compute missing capabilities relative to competitors or derive recommendations. That is a semantic mismatch with the stated purpose of identifying strategic gaps and opportunities.

Static analysis

No suspicious patterns detected.