T09 · Insecure Skill Coding Practices
- Location
scripts/scan.py:253- Finding
Server-Side Request Forgery Through Unvalidated Sitemap URLs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent website scanner, but it needs review because scanned sites can steer it into making unintended outbound requests from the user's environment.
Review before installing. Use this only against public or authorized targets, preferably from an isolated environment with restricted egress, because a scanned site can influence follow-up requests through sitemap data. Avoid scanning internal domains or sensitive investigations unless third-party lookups and outbound disclosure are acceptable.
scripts/scan.py:253Server-Side Request Forgery Through Unvalidated Sitemap URLs
The skill clearly instructs use of network access, shell commands, and report output, but it declares no explicit tool scope or permissions boundary. In an agent setting, this can lead to over-broad execution authority, making it easier for the skill to trigger unexpected network calls, shell execution, or file writes without transparent user consent or enforcement.
The description presents comprehensive website scanning and third-party checks without warning that user-supplied domains and page content will be transmitted to external systems such as DNS resolvers, WHOIS servers, websites being scanned, search engines, or optional third-party services. This creates a privacy and operational risk because sensitive targets or investigation intent may be disclosed during scanning.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Ubuntu/Debian
sudo apt-get install dnsutils
# macOS
brew install bind
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Ubuntu/Debian
sudo apt-get install dnsutils
# macOS
brew install bind
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Ubuntu/Debian
sudo apt-get install dnsutils
# macOS
brew install bind
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
for record_type in cls.RECORD_TYPES:
try:
result = subprocess.run(
["dig", "+short", "-t", record_type, domain],
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def query_whois(domain: str) -> Dict:
"""Query WHOIS data for domain"""
try:
result = subprocess.run(
["whois", domain],
capture_output=True,
text=True,
The scanner automatically performs multiple external lookups to third parties and target-controlled endpoints, including ipapi.co, Google, DNS/WHOIS infrastructure, and optionally sitemap-derived pages, without a clear user-facing disclosure or consent boundary. In a security-tool context, this can unintentionally leak the target being investigated, the operator's IP/user agent, and internal or sensitive domains if users scan non-public assets.
The manifest explicitly states that deep scanning supports Playwright for client-side rendered pages, but the deep scan code only performs additional plain HTTP GET requests with requests/BeautifulSoup and extracts static HTML titles. There is no Playwright import, browser automation, or JavaScript-rendered page handling anywhere in this file, so the advertised capability is not actually implemented.
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking releases, especially for a network-facing scanning tool that relies on HTTP functionality.
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
reportlab>=3.6.0
Because requests is not pinned, there is no way to verify from this manifest whether the installed version includes fixes for known advisories. In a website scanning tool that makes outbound HTTP requests, dependency ambiguity increases the chance that a vulnerable build is deployed and exposed to attacker-controlled URLs or responses.
Using an unpinned beautifulsoup4 version makes builds non-deterministic and may pull in newer releases without prior testing. While not inherently exploitable by itself, it increases supply-chain and stability risk for the skill's web-content parsing functionality.
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
reportlab>=3.6.0
lxml is unpinned even though it is a complex parser with a history of security advisories. In a website scanning skill that parses remote HTML/XML content, allowing arbitrary future versions increases the chance of introducing parser-related vulnerabilities or regressions into production.
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
reportlab>=3.6.0
The manifest does not prove which lxml release will be installed, despite lxml having multiple historical advisories. Given this skill parses remote website content, any unresolved parser or sanitizer flaws in the installed version could become reachable through attacker-supplied HTML/XML data.
reportlab is specified with only a minimum version, so installs may resolve to unknown releases, including ones with security issues. This is more concerning because reportlab has had high-impact bugs historically, and PDF/report generation often processes untrusted content gathered from scanned websites.
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
reportlab>=3.6.0
reportlab has known high-impact advisories, and the unpinned requirement means the deployed version cannot be verified as safe. This matters more in this skill because scanned website content may later be embedded into generated reports, potentially exposing PDF generation paths to untrusted input.
The function documentation suggests a straightforward WHOIS query, but the implementation parses and returns specific registrant organization and country fields in addition to basic domain data. While related to WHOIS, the docstring understates the collection of registrant-identifying information.
The docstrings for fetch_robots_txt and fetch_llms_txt say 'Fetch and parse', which implies structured interpretation of these files. In reality, both functions only download the file and return raw text slices or status strings, with no parsing logic beyond simple retrieval.
The JSON report function writes directly to a user-supplied filename, and the PDF report function likewise creates output files, but there is no confirmation prompt or warning that existing files may be overwritten. The operation is not destructive in a severe sense, but it is a file write affecting local user data without clear disclosure at the point of action.