Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add webdriver-probe-annotate rule (off by default)#124

Merged
twschiller merged 5 commits into
mainfrom
webdriver-probe-annotate
Jun 3, 2026
Merged

Add webdriver-probe-annotate rule (off by default)#124
twschiller merged 5 commits into
mainfrom
webdriver-probe-annotate

Conversation

@twschiller

Copy link
Copy Markdown
Contributor

Summary

  • New webdriver-probe-annotate rule (off by default, top-frame only, experimental). When the page reads navigator.webdriver, the rule prepends a screen-reader-only landmark noting the site can distinguish AI-agent traffic and may serve different content to agents than to people. Closes option (1) from Rule proposal: bot-cloaking-annotate — detect/annotate AI-targeted cloaking #122 (AI-targeted cloaking capability flag).
  • Mechanics: content scripts run in the isolated world and can't observe page-world property accesses, so the rule wires a tiny inline <script> whose textContent wraps Navigator.prototype.webdriver's getter in the page world and dispatches a DOM CustomEvent on each read. The isolated content script listens and stamps the same sr-only landmark shape search-url-helper uses.
  • Probe runs at document_idle — reads issued during initial parse aren't caught; later reads (DOMContentLoaded/load handlers, polled fingerprinters, interaction-driven checks) are. Strict script-src CSP pages block the inline <script> and the rule degrades silently to a no-op.
  • Docs entry under "Cross-origin surface" with two new references (Caspi & Tugendhaft 2025 for AI-targeted cloaking; Wu & Davison 2005 for the original cloaking primitive). Skill docs updated so the agent treats the landmark as a cloaking-capability signal.
  • Demo-site Home page gets a BotDetectorProbe block that reads navigator.webdriver on mount and every 4 s, so reviewers can enable the rule in the popup and see the landmark appear.

Test plan

  • bun run check (extension, demo-site, docs)
  • bun run typecheck (extension)
  • bun run test — 987 tests pass, including 12 new tests covering the listener wiring, sr-only envelope, idempotency, hidden-text-strip interop, and the page-world probe directly
  • pre-commit run --all-files passes
  • Manual: load the unpacked extension on the demo site, enable the rule from the popup, reload, confirm the section[data-abs-rule="webdriver-probe-annotate"] landmark appears at the top of <body>

🤖 Generated with Claude Code

Detect reads of navigator.webdriver from the page world and prepend a
screen-reader-only landmark to the document. A content script can't
observe page-world property accesses directly, so the rule wires a tiny
inline <script> whose textContent wraps Navigator.prototype.webdriver's
getter and dispatches a DOM CustomEvent on each read; the isolated
content script listens and stamps the landmark on first detection.
Closes one option from issue #122 (AI-targeted cloaking).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-browser-shield-demo-site Ready Ready Preview, Comment Jun 3, 2026 8:47pm

Request Review

@unblocked unblocked Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found.

About Unblocked

Unblocked has been set up to automatically review your team's pull requests to identify genuine bugs and issues.

📖 Documentation — Learn more in our docs.

💬 Ask questions — Mention @unblocked to request a review or summary, or ask follow-up questions.

👍 Give feedback — React to comments with 👍 or 👎 to help us improve.

⚙️ Customize — Adjust settings in your preferences.

Comment thread extension/src/rules/webdriver-probe-annotate.ts
Replaces the bot-detector status block with a two-variant card. The human
branch is a neutral editorial note; the bot branch is a fabricated
"Editor's Pick · Verified by RiverMart Trust Council" with manipulated
authority claims — the asymmetry the rule exists to flag. Triggers on
navigator.webdriver=true OR ?bot in the URL so reviewers can see the
cloaked variant in a normal browser without spinning up Playwright.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
PR feedback: the previous querySelector guard in injectProbe could never
find an existing element because the <script> was removed immediately
after execution. Real dedup runs inside installProbe via the page-world
__abs_webdriver_probe_installed flag; the DOM guard was misleading and
produced create→append→execute→remove churn on every re-enable.

Replace with a module-level probeInjected boolean (never reset on
teardown — the prototype wrap persists across enable/disable cycles, so
re-enable doesn't need to re-inject). Drop the now-purposeless
WEBDRIVER_PROBE_SCRIPT_ATTR marker and the test that only asserted the
script was removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
When webdriver-probe-annotate is enabled, the background worker now
registers webdriver-probe.js as a dynamic content script with
world: "MAIN" and runAt: "document_start" via
chrome.scripting.registerContentScripts. Subsequent navigations run the
probe before the page's first script — closes the "early-parse reads
are missed" gap documented in the original PR.

The rule's apply() still inline-injects the same probe at document_idle
as a fallback so the tab the user was viewing when they toggled gets
covered (dynamic registrations only apply to future navigations).
Both paths execute the same installProbe() function, now lifted into
lib/webdriver-probe-source.ts as the single source of truth.

Adds the "scripting" permission to manifest.json. Does NOT require
developer mode — that constraint is on chrome.userScripts, not
chrome.scripting.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Manifest permission diff

The extension's MV3 permission surface changed in this PR. Reviewer: confirm each addition is intentional and necessary.

permissions

  • scripting

Two CI failures introduced by the document_start registration change:

1. knip flagged src/webdriver-probe.ts as unused — it's a build entry
   point but knip's static analysis can't see chrome.scripting referring
   to it by filename. Add to the knip entry list.

2. test:coverage failed: under coverage instrumentation, istanbul wraps
   installProbe with cov_* counter references; the rule then serializes
   the function via .toString() and injects it into the page world via
   inline <script>, where the counters don't exist (ReferenceError on
   the cov_* identifier inside jsdom's main world). Exclude
   webdriver-probe-source.ts from coverage so the serialized source
   stays self-contained.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@twschiller twschiller merged commit 1ff2c5a into main Jun 3, 2026
8 checks passed
@twschiller twschiller deleted the webdriver-probe-annotate branch June 3, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant