Skip to content

SilentBlock 2.0.0: rebuild on compiled filter lists - #1

Merged
ccmrik merged 7 commits into
mainfrom
v2-rebuild
Sep 28, 2026
Merged

ccmrik merged 7 commits into
mainfrom
v2-rebuild

Conversation

@ccmrik

@ccmrik ccmrik commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

What

A ground-up rebuild. The 1.x engine (226 hand-picked domains plus page patches on every site) is replaced by the real filter lists compiled into Chrome's native blocker at build time.

1.6.0 2.0.0
Network rules 39 (226 domains) ~20,700 (EasyList, EasyPrivacy, uBO lists, EasyList Cookie)
Generic hiding ~200 selectors, CSS in every frame ~27,500 selectors, only matching ones injected
Site-specific fixes Valnet + Facebook, hardcoded ~28,000 hosts of CSS, ~8,200 scriptlets
Page API patches on ordinary sites fetch, XHR, sendBeacon, Image, window.open, classList, style.filter none

Real-web smoke test (headless Chromium): speedtest.net 3,531 requests down to 39, theguardian.com 655 down to 148, page content unchanged.

Review findings fixed

  • Settings wiped on every extension and Chrome update. Now migrated, never reset.
  • Any page could switch SilentBlock off with document.dispatchEvent(new CustomEvent('__sb_disable')).
  • Per-site pause left the cosmetic CSS running.
  • Update-check alarm was recreated on every worker wake, so it never fired.
  • Our own CSS hid the anti-adblock bait. The ad counter was overwritten per iframe.
  • No third-party scoping, so Google Ads, GA4, GTM preview and Hotjar-style dashboards broke.
  • Global blur ban, forced overflow:auto, "whitelist" heuristic deleting admin-panel dropdowns.
  • Firefox build had no background script.

Full list in CHANGELOG.md.

Verification

  • npm run check: build (selectors and regexes validated in Chromium), 29 unit tests, CDP load check, 39 Playwright tests against the real build.
  • web-ext lint on the Firefox build: 0 errors.

After merge

Tag v2.0.0 and the release workflow attaches the Chrome and Firefox zips. Anyone on 1.x loaded from another folder must remove it, since unpacked folders get separate extension ids.

🤖 Generated with Claude Code

ccmrik and others added 7 commits September 25, 2026 15:57
Replaces the 1.x engine (226 hand-picked domains plus global page patches) with
EasyList, EasyPrivacy, the uBlock Origin lists and EasyList Cookie compiled at build
time into ~20,700 declarativeNetRequest rules, token-matched generic hiding,
per-site CSS and 33 uBO-compatible MAIN-world scriptlets.

Fixes from the 1.x review:
- settings were wiped on every extension and Chrome update (now migrated, never reset)
- any page could switch SilentBlock off via the __sb_disable DOM event
- per-site pause left cosmetic CSS running
- update-check alarm reset on every worker wake, so it never fired
- own CSS hid the anti-adblock bait; ad counter overwritten per iframe
- no third-party scoping, so vendor dashboards (Google Ads, GA4, Hotjar) broke
- global blur ban, forced overflow, and "whitelist" heuristics broke real sites
- Firefox build had no background script and mixed browser.* with callbacks

Build validates selectors and regexes in real Chromium (one rejected regex stops
Chrome loading the extension). 29 unit tests, 39 Playwright tests on the real build.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DNR cannot block popups, so the 3,000 $popup filters were being dropped and
canyoublockit's click-anywhere pop-under got through. The build now compiles
them to popups/<category>.json; the service worker follows new tabs a page
opens (onCreatedNavigationTarget, then each top-level hop for 8s) and closes
any that land on a matching URL. A tab navigated to an ad within 3s of opening
a popup is sent back and its duplicate closed (tab-under). Tabs opened from
webmail and ad consoles are excepted so tracked links keep working.

$script,popup style filters now keep their network half instead of being
dropped whole.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Icon: one shield, five states. Slate blue (nothing to block), green (ads and
trackers blocked), amber (pop-up, tab-under or nag wall dealt with), red
(malware or scam host blocked), grey (paused or off). Counts are live, from
read-only webRequest watching, so the popup no longer needs activeTab.
Icons are rendered by scripts/icons.mjs.

Security category: uBO Badware, URLhaus, Phishing URL Blocklist and
DurableNapkin's scam list. ~46k hosts blocked by DNR at priority 2000, above
list exceptions and a user's pause; ~36k page URLs checked by the worker on
each navigation (as DNR rules they would blow the 30k guarantee). Listed pages
get a warning page with Back to safety / Continue anyway (session-only
bypass). No API keys and no remote lookups.

Also fixes a race where a tab-under could beat the popup opener's async
registration: the opener is now registered synchronously.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The worker's whole-host danger list copied requestDomains from every security
rule, including uBO badware rules that are a TLD plus a URL pattern (e.g.
`/c/*?s1=$doc,to=com` -> requestDomains:["com"] + urlFilter). That put com,
net, org, ru and ~30 other TLDs on the list, so any .com page (manofmany,
canyoublockit) got the warning page. The DNR rules themselves were correct.

- Only rules that block a whole host (requestDomains + resourceTypes, including
  main_frame) feed security/hosts.json; bare TLDs are refused at build and in
  the worker.
- Page-URL entries now use ABP separator semantics (src/shared/url-match.js):
  bit.ly/6Y3zq^ no longer matches bit.ly/6Y3zqABC.
- Build tripwire: fails if the danger list would cover a major site or shared
  platform (github.io, pages.dev, docs.google.com's parent, bit.ly, ...) or a
  page entry is just "/".
- Regression rule `/sb-tld-scoped/$doc,to=test`: if the TLD leak returns, every
  .test page in the e2e suite gets the warning page.

Verified on the live web: manofmany, canyoublockit, speedtest, the Guardian,
clickclickmedia, ABC, GitHub all load with 0 danger hits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Walls also turn up inside embedded players and sandboxed page frames (Claude
artifacts render in one). executeScript now targets allFrames; covered by a
cross-origin iframe e2e test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ccmrik
ccmrik merged commit 7e25dd8 into main Sep 28, 2026
1 check passed
@ccmrik
ccmrik deleted the v2-rebuild branch September 28, 2026 05:42
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