Skip to main content

v0.0.107

Released Oct 9, 2026


Release Notes

squirrelscan can now probe, politely: a new probing intensity setting decides how much an audit may send, and the first two probing rules (GraphQL introspection and GraphQL mutations over GET) use it. There is also a rule for auth tokens kept in web storage, a rule for a CSP that blocks the page's own resources, quieter secret scanning, and the entity page filter now behaves the same in the CLI, the MCP tools and the hosted API.

Added

  • security/token-storage flags JWTs and session or access tokens written to localStorage or sessionStorage. Anything in web storage can be read by any script on the page, so one XSS bug turns a stored token into an account takeover, where an httpOnly cookie would not. It is passive: it reads the inline scripts and the external scripts the crawl already fetched and sends no extra request. A key is split into words, and whole words decide, so access_token, jwt and idToken flag while theme, dismissed and csrf do not; a value shaped like a JWT flags under any key. The report names the script and the key and never prints the value.
  • Two GraphQL probing rules, the first rules that use probing intensity. They run only when probing is active or aggressive, probe only the audited origin, and on a passive run send nothing. Both probe the GraphQL endpoints the audit found in your pages and scripts, plus /graphql and /api/graphql, at most five per rule, and never a path that names a state-changing action such as logout or delete. Below aggressive they skip paths robots.txt disallows. security/graphql-introspection sends one GET with the read-only query {__schema{types{name}}} and warns when an endpoint returns its schema, naming the endpoint and the type count; on an aggressive run it may follow up with one POST of the same query when the GET answer is GraphQL without a schema. security/graphql-get-mutations sends one GET with the no-op mutation mutation{__typename}, which cannot write, and fails when the server executes it, because a mutation reachable by GET can be fired cross-site with your visitors' cookies (CSRF). Disabled introspection, errors, a 405 and HTML or catch-all answers are not flagged. See Security configuration. That makes 301 rules, 20 of them in Security.
  • security/csp-blocks-own-resources flags a Content-Security-Policy that blocks what the page itself loads. It matches each page's own policy (the header and any <meta http-equiv> policy) against the page's scripts, preloaded modules, stylesheets, frames and images using real source matching, so *.example.com allows cdn.example.com but not example.com. It also looks inside the same-site chunks a page loads for third-party script URLs, and checks the hosts a detected vendor needs at runtime (Google Analytics 4 and Google Ads endpoints, Google Tag Manager, PostHog, Stripe, Cloudflare Turnstile, reCAPTCHA), which the HTML never names. A blocked analytics, ads, payments, captcha, form or booking host fails and any other host warns, naming the directive and the host to add. A page with no enforced policy passes, because a missing CSP stays with security/csp. See the rule page. That makes 298 rules, 17 of them in Security.
  • Probing intensity, a third audit setting next to coverage and render mode. --probe (-P) takes passive, active or aggressive, with --passive and --aggressive as shortcuts and --pentest for --coverage full --probe aggressive. --probe-budget caps the wall-clock time of all probing together (default 30s active, 2m aggressive). [security] probe and budget set both in config. A logged-in audit defaults to active and a logged-out one to passive; aggressive is never a default. --disable-discovery-probes keeps probing passive. No probing rules ship yet, so no audit sends anything new: this adds the setting and the shared budget future rules will use. See Security configuration.

Changed

  • Publishing from a large cloud audit no longer slows down as a site's page history grows. The merge indexes the prior pages once instead of copying them several times, builds the full page list only when something reads it, and writes back only the pages the run changed. At 25,000 pages this removes tens of milliseconds of cold-start work per publish.
  • The send_feedback tool description in the local MCP server is neutral about when to use it, and a test now fails when the MCP docs drift from the tools the server lists.
  • squirrel entities and the MCP list_entities tool now apply the same page filter rule as the hosted API, and a filtered result keeps summary site-wide. --page with an absolute http(s) URL is a prefix of the page URL, a value starting with / is a prefix of the path and query (so --page /blog no longer matches https://example.com/tag/blog), and anything else is a substring. Use --page blog for the old substring behavior. A filtered squirrel entities -f json and list_entities used to return a summary recomputed over the matching entities. They now return the site-wide summary and a new filtered: { nodes, edges } block with what the filters kept, so scripts that read summary.nodeCount after a filter should read filtered.nodes instead. --diff still compares recomputed summaries.
  • The audit also fetches the same-site script chunks a page preloads with <link rel="modulepreload"> or <link rel="preload" as="script">, so security/csp-blocks-own-resources can read the third-party script URLs inside them. They are kept apart from the scripts every other rule reads, so no other rule's result changes, and they are fetched only when a crawled page enforces a CSP, capped at 20 extra fetches per audit. The rule cache format changed, so the first audit of each site after the upgrade runs every rule fresh, once.

Fixed

  • security/leaked-secrets raises fewer false alarms. A label that ends in a credential word, such as a translated Password: heading in compiled JSX, is no longer read as a key whose value is the markup after it, template expressions and placeholder connection strings are not credentials, and a key that runs past a provider's format is reported as a secret of unknown provider instead of being named as that provider's. Public vendor identifiers in a script's query string (Mida, Klaviyo and reCAPTCHA site keys) are skipped. A Statsig secret- key is reported as a server secret and a client- key as the public SDK key it is.
  • A site that sends response headers and then stalls its body can no longer hang the CLI. The shared request helper used by the reachability check, the robots.txt fetch and the update check disarmed its timeout as soon as the headers arrived, so the body read had no time limit. The timeout now covers the body too, and a stalled body fails like any other timeout.
  • The audit engine can keep the cloud results it has already paid for when its caller stops the cloud analysis step at a deadline, instead of discarding all of them. A caller turns this on with the new deadlineMs option on the container prefetch (or by passing its own accumulator and calling abandon()). Results that came back are used by the rules, rules still waiting report skipped with reason service-unavailable, and no new cloud call starts after the deadline. The spend lists each call known to be charged, once: every call that came back, plus a render batch the cloud accepted but had not finished. A call still running at the deadline is not listed and may yet be charged, so the estimated balance after the run is marked approximate (balanceAfterApproximate). Nothing in the CLI sets a deadline, so CLI audits are unchanged, and a prefetch that finishes in time returns exactly what it did before. See credits.

Update to this version

squirrelscan will auto-update, or run this command to update now:

$

Downloads

macOS

Detected
Apple Silicon (M-series)
squirrel-0.0.107-darwin-arm64 · 69.7 MB
Download
SHA-256
Intel
squirrel-0.0.107-darwin-x64 · 76.1 MB
Download
SHA-256

Linux

x64 (musl/Alpine)
squirrel-0.0.107-linux-x64-musl · 81.4 MB
Download
SHA-256
ARM64
squirrel-0.0.107-linux-arm64 · 87.3 MB
Download
SHA-256
x64
squirrel-0.0.107-linux-x64 · 87.4 MB
Download
SHA-256
ARM64 (musl/Alpine)
squirrel-0.0.107-linux-arm64-musl · 80.6 MB
Download
SHA-256

Windows

x64 (Intel/AMD)
squirrel-0.0.107-windows-x64.exe · 93.4 MB
Download
SHA-256

Audit your site in one command

SEO, performance, security, accessibility and agent experience issues, with exact fixes for your coding agent.

Install
$

No account needed for the CLI. Cloud audits include free monthly credits.