squirrelscan
GitHub

Cloaking: showing Googlebot a different page

An injected payload can hide from you by branching on user-agent or a query token. squirrel re-fetches suspicious paths and compares the responses.

What cloaking is

Cloaking is serving materially different content to a search engine crawler than to a person. Google’s spam policies treat it as a violation on its own, but on a site that did not choose to do it, cloaking is usually a symptom: an injected payload branches on the user-agent so the owner sees a clean page while the crawler indexes the spam.

Token-gating is the same idea keyed on the URL instead. The page returns nothing interesting until a query parameter the attacker distributes is appended, which keeps the payload out of ordinary crawls. Legitimate personalisation by geography or device is not cloaking as long as the indexable content stays the same.

What squirrel checks

The rule reads the results of an opt-in differential probe that runs after the crawl and before the rules. The probe picks a small, capped set of suspicious paths, meaning pages that are orphaned, with no inbound internal links and absent from the sitemap, or recently modified according to sitemap lastmod. It never picks the homepage or the page the audit started from. A lastmod that names only a year, a month or a day (2026, 2026-10, 2026-10-14) counts from the end of that period, or from now when the period has not ended, so a page stamped with the current year or month is recent. It re-fetches each one with the default user-agent, again with a Googlebot user-agent, and optionally once more with an appended query token, then compares HTTP status and visible-text similarity.

The rule emits these checks:

  • cloaking passes when the probe ran but found no suspicious paths to test. Message: No suspicious paths to probe for cloaking.
  • cloaking fails for paths where the Googlebot response diverges. Message: 2 page(s) serve different content to googlebot than to a normal visitor — likely cloaking. The reported value describes up to five of them, either as /path: googlebot got 200, normal visitor got 404 (UA-gated response) or as /path: googlebot content only 12% similar to the normal-visitor page.
  • cloaking-token-gated warns for paths whose response changes when a query token is appended, excluding any already reported as UA cloaking. Message: 1 page(s) change their response when a query token is appended — possible token-gated content.
  • cloaking passes when paths were probed and neither pattern appeared. Message: Probed 8 suspicious path(s) — no UA cloaking or token-gating detected.

When the probe is off, the rule emits nothing. It never reports a path it did not probe as clean. Severity error, weight 7.

Rule IDintegrity/cloaking
CategorySite Integrity
ScopeSite-wide
Severityerror
Weight7/10

Enable the probe

The probe is off by default. It adds two requests per selected path, or three when query variation is on, and the page cap is what bounds that extra work.

[integrity.cloaking_probe]
enabled = true            # off by default
max_pages = 10            # hard cap on probed paths (1–50)
recent_days = 14          # sitemap lastmod within N days counts as "recent"
query_variation = true    # also probe an appended query token (token-gating)
# googlebot_user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

How to fix it

curl -A 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' https://example.com/path

Fetch the URL yourself with a Googlebot user-agent to see how the server responds to that string. A server can also identify Googlebot by reverse DNS on the request IP, so a spoofed user-agent shows you the user-agent branch and not necessarily what Google receives. Then look for server-side rules that branch on user-agent or query string, and audit recently modified files and plugins.

Paywalls and A/B tests can produce a similarity divergence without being cloaking. Confirm what the Googlebot response actually contains before treating a finding as a compromise.

Enable / disable

Disable this rule

[rules]
disable = ["integrity/cloaking"]

Disable all Site Integrity rules

[rules]
disable = ["integrity/*"]

Site Integrity findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Site Integrity section of the report. Each probed path is listed with the two status codes and the similarity score. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close