v0.0.142
Released Oct 30, 2026
Release Notes
squirrel audit follows a start URL that redirects, with your consent, and an unreachable start URL now writes a report and exits 5. Pages with no markup no longer fail every DOM rule, a relative sitemap loc no longer breaks the URL rules, labelled menu sections and label elements are counted correctly, and leaked-secret findings carry the matched value's length and offset.
Added
- Leaked-secret items now include the matched value's character length and zero-based source offset in
meta; inline-script items also identify the script's position in the page. Values remain masked in reports. See Leaked API key in client-side code. (#1230) squirrel auditaudits where a start URL redirects, not the redirector.squirrel audit bit.ly/abcused to score bit.ly. The start URL's redirect chain is now resolved before anything is crawled, estimated or named, one request per hop through the same egress guard as the crawl, capped at 5 hops. A redirect within one site (httptohttps, apex towww, a path) is followed silently. A redirect to another registrable domain needs your consent: a terminal asks (bit.ly/abc redirects to https://example.com/pricing. Audit example.com instead? [Y/n]), and anything else needs--follow-redirector[crawler] follow_redirect = true. Without it the run does not crawl or score the redirector: it exits4with aredirectedreport that names the destination, the chain and the command to run again, in every output format.-ydoes not imply the consent, because it approves credit spend and the redirect may land on a site that is not yours. A chain that detours through another domain and back counts as another site. Reports and prompts name each hop by scheme, host and path only, and the destination is audited at its origin and path: its query, fragment and userinfo are dropped, so a destination that needs them has to be audited by typing it directly. The hops are requested before the credit check and registration. A loop, a chain past 5 hops, or a hop into a private, link-local or metadata address also exits4and is never followed. A followed redirect is recorded in the report (meta.originalUrlandmeta.redirectChainin JSON, a scan note in the text, markdown, LLM, XML and HTML reports), the project and the credit estimate are the destination's, and the MCPaudit_websitetool answersconfirmation_requiredwith the destination until called withfollowRedirect: true. See Start URLs that redirect. (#1281)
Fixed
- A relative sitemap
<loc>no longer breaks every URL rule. A sitemap that lists<loc>/pricing</loc>, as some sites do, put the path itself into the crawl as the page's URL, andurl/length,url/parameters,url/slug-keywords,url/trailing-slash,crawl/paginationandschema/website-searchfailedInvalid URLon every page. Pages are now stored under their absolute URL, a relative<loc>is resolved against the sitemap's own URL, andcrawl/sitemap-validreports the entries that are not absolute URLs, as the sitemap protocol requires. (#1274) a11y/form-field-multiple-labelscounts label elements, not references. A<label for="a">that also wraps the controlid="a"was counted twice and reported as "2 labels", which fires on every Shopify Dawn variant picker. Labels are now collected as a set the way a browser'sinput.labelsdoes: one wrapping-and-forlabel is one label, a wrapping label whosefornames another control does not label this one, and a wrapping label labels only its first labelable control. Two real labels on one control still warn with an accurate count. (#1249)a11y/image-redundant-altno longer flags a readable alt that spells the filename.alt="Google Partner Logo"ongoogle-partner-logo.svgwas reported only because both read the same once spaces and hyphens were removed. The filename test now needs the alt to look like a raw filename or slug (a single token, or the decoded filename spelled exactly), soalt="arrow-downwards"onarrow-downwards.svgstill warns and the prefix, surrounding-text and figcaption checks are unchanged. (#1273)- A page with no markup no longer fails every DOM rule. An empty, whitespace-only, comment-only, plain-text or JSON-as-
text/htmlresponse left the parser with a document that has no root, anddocument.head/document.bodythrew, so each rule touching them reported a bogusRule errorfail and lowered the score. Such a page now parses like a browser reads it: an empty<html><head></head><body></body></html>, with any text in the body. (#1270) - A quote, backslash or bracket in an
idorforno longer breaks the label rules.a11y/form-labels,form-field-multiple-labels,select-name,aria-input-field-name,aria-toggle-field-name,aria-meter-name,aria-progressbar-name,aria-command-name,aria-required-parent,aria-required-childrenandsecurity/form-captchabuilt CSS selectors from page values and threwAttribute selector didn't terminate. They now compare attribute values as plain strings, and a guard test fails if a rule interpolates a value into an attribute selector again. (#1276) meta.auditLevel.settingssays what an--offlinerun did. It reported the level's cloud defaults (cloudChecks,render: "all",externalLinks) on every offline report, although nothing was rendered or checked in the cloud. An offline run now records those three as off, withoffline: truebeside them, andlevelandbasedOnstill name the level you asked for. The LLM, markdown, text and HTML outputs say the audit ran offline too. (#1275)- An unreachable start URL writes a report and exits
5. DNS failure, connect timeout, connection reset or refused and TLS errors used to exit1with a line on stderr and no file. With-f json(orxml,llm) the run now writes{ "status": "unreachable", "statusReasonCode", "statusReason", ... }to--outputor stdout, so a batch job can tell a down site from a crash. Breaking for scripts: ablockedreport now always exits3, with or without an identified WAF vendor; a bare 403 or 429 used to exit1, so a CI step that treats only1as failure needs to accept3too. See Unreachable start URLs. (#1269)
Update to this version
squirrelscan will auto-update, or run this command to update now:
$