Install
Prerequisites
Section titled “Prerequisites”- Chrome / Chromium 148+ — to load the extension. Any Chromium-based browser works (Chrome, Edge, Brave, Arc, Opera).
- Node ≥ 24 and Bun ≥ 1.3 — only needed if you’re building from source.
Install from the Chrome Web Store
Section titled “Install from the Chrome Web Store”The simplest path for everyday use. Install the published extension on any Chromium-based browser:
Add to Chrome — Chrome Web Store
Updates roll out automatically through the store. Skip the rest of this page
unless you need an unpacked build (agent runtimes that load via
--load-extension), a ZIP for Browserbase, or a build off a specific commit.
Download a prebuilt ZIP
Section titled “Download a prebuilt ZIP”Every release attaches the packaged extension to the GitHub Release. The
latest redirect follows the most recent release:
https://github.com/pixiebrix/agent-browser-shield/releases/latest/download/agent-browser-shield-extension.zipmanifest.json is at the archive root, so the ZIP can be uploaded straight to
Browserbase, or unzipped and loaded into Chrome as
an unpacked extension (see Load it into Chrome). Do not
re-zip after unpacking.
Build from source instead if you’re iterating on rules or want a specific commit.
Build the extension
Section titled “Build the extension”Clone the repository and build the extension bundle:
git clone https://github.com/pixiebrix/agent-browser-shield.gitcd agent-browser-shield/extensionbun installbun run buildBuild output is written to extension/dist/.
Load it into Chrome
Section titled “Load it into Chrome”- Open
chrome://extensions. - Enable Developer mode (top right).
- Click Load unpacked and select either
extension/dist/(built from source) or the directory you unzipped the prebuilt ZIP into.
The extension is now active. Reload any open tabs to pick up the content script.
Reading the toolbar icon
Section titled “Reading the toolbar icon”The toolbar icon answers “am I protected on this tab?” at a glance, so you don’t have to open the popup:
- Blue shield, no badge — protected, nothing scrubbed on this page yet.
- Blue shield with a number — protected; the number is how many things the
shield acted on across all frames of the tab. A count over 999 shows as
999+. - Amber badge — a site-level detection worth opening the popup for (for
example, a hard-to-cancel subscription). When there’s a detection but no
count, the badge shows
!. - Greyed shield with an
offbadge — enforcement is paused on this tab, because you turned the master switch off (every tab), the site is on your Disable on this site list, or you used a temporary recovery pause (Reveal everything on this page or a snooze) on this tab. Hover the icon to see which.
Recovering a page the shield broke
Section titled “Recovering a page the shield broke”If a rule hides something you actually wanted, open the popup for two quick, temporary escapes — both scoped to the current tab and forgotten on their own, so they never become a setting you have to remember to undo:
- Reveal everything on this page — one click un-hides everything the shield scrubbed on the current page and stops it re-hiding for this page view. It’s the panic button: reload the page (or navigate away) and protection comes back.
- Pause protection — snooze the shield on this tab for 15 min, 1 hour, or until you close the tab. Unlike Reveal everything, a snooze carries across page navigations in the same tab, so you can get through a multi-step flow like a checkout. The popup shows the time remaining and a Resume now button; when a timed snooze runs out while you’re still on the page, the page stays as-is and protection re-engages the next time you navigate.
Both are deliberately separate from Disable on this site, which is a permanent choice saved until you remove it. Use the recovery controls for a one-off; use Disable on this site for a site you never want the shield to touch.
Customizing defaults at build time
Section titled “Customizing defaults at build time”Which rules ship on by default is enumerated in
extension/src/rules/rule-metadata.ts.
For one-off changes, edit that file and rebuild.
For infrastructure deployments where the same custom set of defaults should ship
in every build (so an agent doesn’t have to flip toggles in the Options page on
each fresh session), pass a JSON override file to bun run build. A starting
template lives at
extension/data/defaults-overrides.example.json:
cat > my-defaults.json <<'EOF'{ "reviews-redact": false, "ads-hide": false, "optionsButton": true}EOF
bun run build --defaults ./my-defaults.json# or, equivalent:EXTENSION_DEFAULTS_FILE=./my-defaults.json bun run buildThe override file is a flat JSON object. Most keys are rule ids mapped to booleans — the same shape the Options page exports and imports, so a file exported from a tuned extension can be fed straight into the next build. A small set of reserved keys is also accepted for non-rule build-time toggles:
-
optionsButton(boolean, default off) — show the floating shield button in the bottom-right corner of every page that opens this extension’s options page. Off by default because on sparse pages (JSON viewers, error screens, interstitials) it can dominate the accessibility tree and become a misleading target for browser-use agents. Enable for human-facing deployments where on-page access to options is useful. -
runOnInactiveTabs(boolean, default off) — keep the shared subtree watcher observing while the tab is hidden. Off by default because a hidden tab gets no observer callbacks, which avoids work the user can’t see. Enable when something else reads the page while it’s in the background (chat copilots, accessibility-tree agents, sidebar extensions) — without this, a page that mutates while hidden could reach the consumer unredacted. -
debugTrace(boolean, default off) — start with the dev-mode debug-trace recorder enabled. The recorder captures every rule-driven mutation (selector, before/afterouterHTML, segment id) to IndexedDB and exposeswindow.__abs_dumpTrace()for CDP-driven harnesses to scrape — for investigating false positives (a rule hid, masked, or rewrote something it shouldn’t have) after the fact. Enable in builds you ship to automation harnesses (Browserbase, Hermes, browser-use, OpenClaw) so the trace is on every session without a human flipping the popup toggle. See Debug trace for the retrieval recipes and event schema. -
placeholderAdaptivePalette(boolean, default off, experimental) — sample each placeholder’s ancestor backgrounds at insert time and pick a light or dark stripe palette so redactions on dark-themed pages don’t flare against the page chrome. Off by default while the visual heuristic is still being tuned; the toggle is also surfaced in the Options page under the Placeholder display section so humans can flip it without rebuilding. Enable for deployments on consistently dark UIs. -
siteDenylist(array of URL Pattern strings, default[]) — start with these hosts already in the per-site enforcement denylist. When the active tab’s top-frame URL matches any entry, every rule is paused on that tab; subframes inherit the tab’s state. Each entry must satisfynew URLPattern(entry)(the build fails otherwise) and accepts the full URL Pattern syntax — including subdomain wildcards (https://*.example.com/*) and path scopes (https://example.com/admin/*). The same key round-trips through the Options-page Export configuration / Apply configuration surface so a tuned extension’s exported JSON can be fed back into the next build. Users author entries one-click from the toolbar popup (“Disable on this site”) and can audit / remove them on the Options page under Sites with enforcement disabled.
A handful of rules expose sub-rule options in addition to the plain on/off toggle. For those, a rule’s value may be an ESLint-style object instead of a boolean:
{ "encoded-payload-redact": { "enabled": true, "subRules": { "leetspeak": false, "nato": false, "morse": false } }}enabled is optional — when absent, the rule’s committed default state is used.
Sub-rule fields are merged over the committed sub-rule defaults; omitted
sub-rules keep their default state. The rules that take sub-rule options and the
fields each accepts are declared in
extension/src/rules/rule-metadata.ts
under RULE_OPTION_DEFAULTS. Today the only rule that takes options is
encoded-payload-redact, which exposes one sub-rule per encoding family
(base64, hex, percent, substitutionCipher, leetspeak, nato, morse)
— useful for turning off the higher-false-positive text ciphers without losing
coverage of the byte encodings.
Each sub-rule may also be an object carrying tuning thresholds — length floors,
common-word counts, printable-byte ratios — that override the file-scope
defaults in rule-metadata.ts:
{ "encoded-payload-redact": { "subRules": { "leetspeak": false, "nato": { "enabled": true, "minWords": 14 }, "morse": { "enabled": true, "validRatio": 0.9 } } }}A bare boolean at a sub-rule is shorthand for { "enabled": <boolean> };
omitted threshold fields keep their committed default. Threshold meanings (and
the rationale for each shipping value) live in the rule source —
extension/src/rules/encoded-payload-redact.ts and
extension/src/rules/rule-metadata.ts. Threshold values are not range-checked
at the validator; operators tuning them are reading the rule source by
definition.
The file may be partial; rules not listed keep the committed default. A bare
boolean still works for any rule, including those with sub-rule options
("encoded-payload-redact": false disables the entire rule). Unknown keys (rule
ids, reserved keys, sub-rule names, or threshold field names), object values for
rules without declared sub-rule options, and leaf values whose type doesn’t
match the declared default (boolean → non-boolean, number → non-finite or
non-number) fail the build with a message naming the offending paths.
Build-time overrides only affect fresh chrome.storage — users who already
toggled rules in the Options UI keep their preferences. The typical target is
short-lived browser instances (e.g. browserbase containers) where storage starts
empty each session.
See Rules for the full list of rule ids and what each does.
Iterating
Section titled “Iterating”bun run watch rebuilds extension/dist/ whenever a file in extension/src/
changes:
cd extensionbun run watchAfter each rebuild, click the reload icon for the extension at
chrome://extensions and refresh any open tabs.
Using it with Browserbase
Section titled “Using it with Browserbase”The
Browserbase extensions API
accepts the prebuilt ZIP directly — download it from
https://github.com/pixiebrix/agent-browser-shield/releases/latest/download/agent-browser-shield-extension.zip
and upload as-is.
To build the ZIP from source instead:
cd extensionbun run buildbun run package # writes output/agent-browser-shield-extension.zip at the repo rootContributing
Section titled “Contributing”See CONTRIBUTING.md for setup expectations and the contributor-license-agreement workflow.