url-validation
Preflight and safety gate for every audit. Use first to normalize a target URL, block SSRF and unsafe schemes, revalidate redirects, inspect robots.txt, establish scope and budgets, and report HTTPS,
Files3
View on GitHubSKILL.mdskills/url-validation/SKILL.md
GitHubURL Validation (preflight gate)
This skill answers two separate questions and must not conflate them:
- Is it safe and in scope to audit this target? A hard gate. If it fails, nothing else runs.
- Does what we learned while checking constitute a finding? Several preflight observations are real discoverability defects and are reported.
When to use
Run this first for every audit, before any other skill in this marketplace. The orchestrator invokes it automatically; run it directly when you want to check whether a target is auditable at all, or to inspect a site's robots posture on its own.
Inputs
| Input | Required | Notes |
|---|---|---|
url |
yes | A bare domain (example.com), a full URL, or a pasted link. Whitespace, wrapping punctuation and fragments are tolerated. |
--max-pages |
no | Page budget for the whole audit. Default 20. |
--max-seconds |
no | Detection budget. Default 150. |
--strictness |
no | lenient, balanced (default), or strict. Shifts derived thresholds, never the safety gate. |
--workspace |
no | Where to create the run directory. Default ./.audit/. |
Procedure
- Normalise. Trim, strip wrapping punctuation, add a scheme when missing, punycode internationalised hosts, drop the fragment, canonicalise the path.
- Gate on safety. Scheme allowlist, credential rejection, obfuscated-IP rejection, reserved-suffix rejection, port allowlist.
- Resolve DNS and require every returned address to be public unicast.
- Resolve the redirect chain, re-validating each hop against the same rules. A public host that redirects into private space is refused at the hop that does so, not after.
- Establish scope as the registrable domain of the final URL.
- Fetch and parse
robots.txt; record how each known AI crawler is treated. - Probe HTTPS and canonical host behaviour (
http→https, apex →wwwor the reverse). - Write the preflight record and emit findings.
Run it:
python3 scripts/validate_url.py <url> [--max-pages N] [--strictness LEVEL] [--json]
Exit codes: 0 cleared, 1 refused (unsafe or unreachable), 2 internal error.
Checks performed
| Check id | Detects | Severity | Claim level |
|---|---|---|---|
no_https |
Site served over plaintext HTTP | high | 1 |
https_not_enforced |
HTTP does not redirect to HTTPS | high | 1 |
redirect_chain_long |
3+ hops before the final document | medium | 1 |
host_canonicalisation |
Apex and www both serve 200 without redirecting |
medium | 1 |
robots_missing |
No robots.txt at all |
low | 1 |
robots_unparseable |
robots.txt present but malformed |
medium | 1 |
robots_blocks_ai_retrieval |
Blocks a live-retrieval AI crawler | critical | 1 |
robots_blocks_ai_training |
Blocks a training crawler only | medium | 1 |
robots_blocks_all |
Disallow: / for * |
critical | 1 |
crawl_delay_excessive |
Crawl-delay high enough to starve a crawler | medium | 2 |
Output
Writes 01-url-validation.json into the run workspace:
{
"cleared": true,
"target": { "url": "...", "origin": "...", "registrable_domain": "...", "resolved_ips": ["..."] },
"redirect_chain": [ { "from": "...", "status": 301, "to": "..." } ],
"robots": { "exists": true, "sitemaps": ["..."], "ai_crawlers": { "GPTBot": { "allowed": false, ... } } },
"config": { "thresholds": { ... } },
"findings": [ ... ]
}
Guardrails
Read-only and recommend-only. GET and HEAD only; never authenticates,
never submits a form, never follows a redirect out of scope, never fetches a
private address. robots.txt is honoured for every subsequent request, not
merely reported on.
Grounding
The AI-crawler distinction is the load-bearing idea. Blocking a training
crawler (GPTBot, Google-Extended, ClaudeBot) affects what a model
absorbs over time. Blocking a live-retrieval crawler (OAI-SearchBot,
PerplexityBot, Claude-User, ChatGPT-User) means the brand cannot be
fetched while an answer is being generated — and arXiv:2604.25707 §6 reports
search-trigger rates of 98.64% (ChatGPT), 99.67% (Google AIO) and 100%
(Perplexity). Retrieval is attempted on essentially every prompt, so a block
at that layer is decisive, which is why the two cases carry different
severities.