v0.0.140
Released Oct 29, 2026
Release Notes
Technology detection now works offline and reads the first-party script bundles of single page apps, so Lovable, Base44, Replit, v0, Supabase, Clerk and Firebase apps are recognised, and its fingerprint patterns are bounded. squirrel audit fails with exit code 3 when a WAF or bot manager serves a challenge or block page, and lists the blocked pages. The installers put squirrel on your PATH, and the in-page About and Contact check, the offline seed redirect and the keyword-stuffing check are fixed.
Added
- Technology detection reports Vercel BotID (Kasada's client served from a Vercel site) as its own technology instead of Kasada, reports F5 BIG-IP from its
BIGipServercookie orServer: BigIPheader, and lists a WAF provider once instead of as both a fingerprint and awaf-twin. BotID and the other providers are technologies only: a normal 200 page behind them is never treated as blocked. (#1253) squirrel auditfails when a WAF or bot manager serves the audited page a challenge or block page. Cloudflare, Akamai, DataDome, Kasada, HUMAN, Imperva, Sucuri, AWS WAF, F5, Vercel, Wordfence and Radware are recognised from provider-specific headers and page markers, on the statuses they use (200,202,403,405,429,503). The audit isblockedwith no score, exits with code3, and says the provider, the marker that matched, the status and what to do; the JSON report carrieswafBlocked.seedwith ablocked_by_<provider>code. A blocked page that is not the audited one is left out of every rule and the score, counted, and listed in the console, text, markdown,llm,jsonand HTML reports. A page that only mentions a vendor, loads its script, or shows a CAPTCHA widget is still audited, and a site with real content behind a WAF still gets the "uses protection" warning. See blocked by a WAF or bot manager. (#1253)- The installers put
squirrelon your PATH.install.shkeeps its directory choice (SQUIRREL_BIN_DIR, then the first of~/.local/bin,~/bin,/usr/local/bin,/opt/homebrew/binalready on PATH and writable), else uses~/.local/binand appends one marked line to the file your shell reads (~/.zshrc,~/.bash_profileon macOS bash,~/.bashrcon Linux bash,~/.config/fish/conf.d/squirrel.fish,~/.profile), once, never rewriting existing content. When your current shell cannot findsquirrelyet, the closing message says so first and gives a command that works right now.install.ps1adds the bin directory to the userPathand the session.SQUIRREL_NO_MODIFY_PATH=1opts out; CI never edits a profile (and appends toGITHUB_PATHwhen set). The install registration reports the outcome aspath_setup, andsquirrel self installno longer prints its own "not in your PATH" block after an installer handled PATH. See the quickstart. - Technology detection recognises Lovable, Base44, Replit and v0 apps, and the Supabase, Clerk and Firebase client SDKs. Each reads only what a stored page holds: generator and author meta tags, platform script URLs, app hosts such as
*.base44.appor*.replit.app, inline client config, and storage image URLs. A page that only mentions a product, links to one of its assets or shows its code in a sample does not match, and a Base44 app is not also reported as Supabase for the shared storage it loads images from. The existing Firebase Hosting signature is unchanged. See Technology detection. (#1242) - Technology detection reads the script bundles of single page apps. A Vite, Lovable, Bolt or Next.js app ships a near-empty HTML shell and keeps its libraries in
/assets/*.jsor/_next/static/chunks/*, so stacks such as Supabase, Firebase and Clerk were missed where they are most common. Detection now reads up to 64 KB of each first-party bundle (512 KB per page, 1 MB per audit): the first 16 KB of every script, then the text around vendor markers and the end of the file, where a bundled app's own code sits, then more of the start. It uses the bytes the crawl already fetched for the secret rules: no extra request. A bundle matches only on real code (a Supabase project URL passed with a key, a FirebaseauthDomainorstorageBucket, a ClerkpublishableKey), not on a comment, a string or a placeholder. Signed-out and--offlineaudits run the same detection locally, and the cloud call sends the same bundle bytes, so both report the same stack for the same crawl. A scan stops at a 5 second budget per page.[tech_detect] bundle_byteschanges the per-bundle cap (0turns bundle matching off). See Technology detection. (#1254)
Fixed
- A challenge a provider served with a
429(Kasada's is one) is no longer retried and reported as rate limiting, and a challenge served as200,202or405is no longer stored and audited as the site. (#1253) - Keyword-stuffing checks measure substantial main copy instead of site chrome. The largest main landmark is used when it has at least 100 words; otherwise the body is measured without site-wide header, navigation, footer and sidebar boilerplate, while article-local landmarks stay in the copy. Unicode words such as
gemäßstay whole, unsegmented Han, Kana and Hangul runs are not scored, and repeated German and English price-note terms are ignored. (#1182) perf/lcp-hintsno longer flags the eager images below a preloaded hero. A page has one LCP element, so one preloaded likely-LCP image satisfies the check; with no image preload it warns once,Likely-LCP image loaded without preload, naming the first candidate instead of counting each eager image. See perf/lcp-hints (#1221).core/charsetno longer warns about a charset meta past the first 1,024 bytes when theContent-Typeheader already names the same UTF-8 charset. The header decides the decoding, so the position is a conformance note: it is now info and does not affect the score, and its message says so. A page with no header charset still warns, a header that conflicts with the meta still gives the conflict warning, and a non-UTF-8 page still gets the non-UTF-8 warning. See core/charset (#1220).- Technology detection no longer stalls on a page that repeats an unclosed tag. The RequireJS signature took about 70 s on a 1 MB page of
<scriptrepeats, and 14 other signatures (Bulma, Foundation, Semantic UI, Materialize, Animate.css, Plausible, Fathom, Facebook Pixel, RudderStack, Dynatrace, Didomi, Ensighten, Yotpo, UserWay) took up to several seconds on the same kind of input. Their patterns now have bounded windows, and a test runs every signature against input built from its own leading text. (#1244) squirrel audit --offlinenow treats a non-localhost start URL that redirects off-site as reachable, so the crawl can record the redirect instead of stopping at the preflight probe withrefused: host outside the allowed set. This also covers link-shortener and sibling-host redirects. (#1224)eeat/about-pageandeeat/contact-pagenow recognise an in-page About or Contact section in a real audit. The v0.0.139 change (#1208) only worked where a page's DOM was still available, which the streaming engine, the one the CLI and the cloud run, does not provide to site rules, so a one-page site still read "No About page found". The section is now collected from each page while its DOM is live. An engine-level test runs the one-page fixture through the streaming engine (#1236).
Update to this version
squirrelscan will auto-update, or run this command to update now: