v0.0.155
Released Nov 1, 2026
Release Notes
Technology detection recognises fewer look-alikes and more real loaders: a Clerk key must decode to a Clerk host (a Stripe publishable key is no longer Clerk), a Next.js script component's bare loader is read, a config past many look-alike strings in a bundle is found, and surge, railway, amplify and ActiveCampaign Pages hosting is read from the page's own host. [[ignore]] entries take element selectors, and --max-duration judges a gzip page by its decoded size, so a small compressed page can no longer force a long parse. Thanks to William for the Clerk key validation (#1481, #1482).
Added
[[ignore]]entries takeselectors. A waiver can now name an element by where it sits (selectors = ["localization-form select"]: tags,#id,.class, descendant and>), so a rule keeps reporting your own elements while it waives the one your platform renders.a11y/label-content-name-mismatch,a11y/form-labelsanda11y/select-namereport the element's place;squirrel config validatenames a rule that does not, refuses an unsupported selector, and the waived items are counted and listed inmeta.ignoredlikeitems. Reports never carry the recorded place. (#1440)
Fixed
integrity/brand-impersonationbounds the logoalttext it reads per control. A control wrapping many logos reads thealtof its first four in full and the next ones for 300 characters, at most 100 in all; a later alt longer than 300 characters, or more than 100 alts, counts the control as not read in full. The window arrays are freed before the reads. (#1424)- A Stripe publishable key is no longer mistaken for Clerk. A
pk_live_orpk_test_value written next topublishableKeynow counts as Clerk only when its body decodes to a Clerk frontend host ending in$; opaque Stripe keys no longer trigger the Clerk signature. (#1478) --max-duration's parse cap judges the decoded page, not the compressed one. The cap (5 MiB, because a parse cannot be interrupted) compared the recorded size, which is the Content-Length header, so a gzip response of a few KB that inflates to megabytes was parsed in full, in the crawl, the audit pass and the streaming pass that counts the pages left out. All three now compare the larger of the recorded size and the decoded body's bytes, so such a page is stored, counted inpagesTooLargeand listed like any other too-large page. A run without--max-durationis unchanged. (#1497)- A Next.js loader written as a bare script child is read when its component is
next/scriptelsewhere on the page. A page uses one component reference for every use, and a real layout passes a Clarity loader as{ type: "text/javascript", children: "..." }with noidand nostrategybeside two uses of the same reference that carry them. Once any use of a reference has one ofnext/script's four strategies, every use of it is read as a script; a reference never seen with a strategy is not, so a component that merely displays a code sample is still dropped. (#1487) - A real Firebase, Supabase or Clerk config deep in a whole bundle is found past any number of look-alike strings. An
inCodedetector gave up after 64 pattern matches that started inside strings, and a whole bundle (the local scan reads one up to 8 MB) holds far more than a 256 KB head: docs text, error messages and vendor snippets that quote a config. The search now continues past the string a match was in, so many mentions in one string are one candidate, and the bound is 4,096. A config that only appears in strings and comments is still not detected, and one that comes after more than 4,095 such matches is still missed, with no truncation signal. (#1422) surge-sh,railway-app,aws-amplify-hostingand ActiveCampaign Pages are read from the page's own host. Their signatures matched.surge.sh,.railway.app,.amplifyapp.comand.ac-page.comanywhere in the page HTML, so a site that only loads a third-party script or links to one of those hosts read as hosted there (the same class as thefirebase-hostingfix). Surge and Railway keep theirServerresponse header signal. (#1449)
Update to this version
squirrelscan will auto-update, or run this command to update now: