Understanding the Three Levels of Blocking in uBlock Origin's Dynamic Filtering
uBlock Origin implements a three-tiered dynamic filtering engine that operates through a master switch, host-level bitmap rules, and URL-level string patterns to determine whether network requests are blocked, allowed, or passed to static filters.
The levels of blocking in uBlock Origin's dynamic filtering provide granular control over network traffic, allowing users to override static filter lists with custom rules. This architecture, implemented in the gorhill/uBlock repository, uses progressive evaluation layers that range from global on/off toggles to specific URL pattern matching.
The Three-Tiered Dynamic Filtering Architecture
uBlock Origin's dynamic filtering system operates as a decision stack that evaluates network requests against three distinct rule layers. Each layer can independently return a block, allow, or noop (no operation) decision, with the engine stopping at the first definitive ruling.
The architecture is designed to prioritize user control: the master switch acts as a global circuit breaker, host-level rules provide efficient bitmap-based filtering for common scenarios, and URL-level rules handle complex exceptions that require pattern matching.
Level 1: The Master Switch
The master switch serves as the global enable/disable control for the entire dynamic filtering engine. When disabled, uBlock Origin ignores all dynamic rules and relies solely on static filter lists.
In the source code at src/js/dynamic-net-filtering.js, this is implemented as a Boolean flag accessed via µb.sessionSwitch or µb.dynamicFilteringEnabled. When the switch is off, the evaluation engine immediately returns "no decision," allowing static filters to process the request.
UI Control: The padlock button in the Dynamic Filtering pane of the dashboard toggles this switch, allowing users to temporarily disable all custom dynamic rules without deleting them.
Level 2: Host-Level Rules
Host-level rules form the core of uBlock Origin's dynamic filtering, operating on the relationship between source hostnames, destination hostnames, and request types. These rules use a highly efficient bitmap storage system rather than string matching.
In src/js/dynamic-net-filtering.js, each rule is represented as a bitmap where specific bit offsets determine the action for each request type. The typeBitOffsets table defines positions for types like script, image, 1p-script, 3p-script, 3p-frame, and others.
How Host-Level Evaluation Works
The evaluation function DynamicHostRuleFiltering.evaluateCellZY() processes rules in order of specificity:
- Explicit rules matching source, destination, and type
- Third-party and first-party shortcut rules
- Generic
* *wildcard rules
The function returns numeric codes: 1 for block, 2 for allow, and 3 for noop. This evaluation occurs in src/js/dynamic-net-filtering.js between lines 35-44 for the type table and lines 71-80 for the evaluation flow.
Common Host-Level Rule Patterns
* * 3p-script block— Blocks all third-party scripts globallyexample.com * script block— Blocks all scripts on example.com regardless of destination* tracker.com * block— Blocks all requests to tracker.com from any source
Level 3: URL-Level Rules
URL-level rules provide the finest granularity, matching full URL patterns including wildcards rather than just hostnames. These rules are essential for exceptions that cannot be expressed through host-only logic, such as allowing a specific image from a CDN while blocking other resources from the same domain.
These rules are stored as plain strings in µb.permanentFirewall and parsed by src/js/url-net-filtering.js (specifically around line 239). Unlike the bitmap-based host rules, URL rules use pattern matching similar to static filter syntax, supporting wildcards like ||example.com/ads/*.js$script,third-party.
UI Control: The text area at the bottom of the Dynamic Filtering pane allows direct entry and removal of URL-level rules.
Evaluation Precedence and Flow
When uBlock Origin processes a network request, the levels of blocking in uBlock Origin's dynamic filtering are evaluated in strict order:
- Master Switch Check — If
µb.sessionSwitchis disabled, the engine returns "no decision" immediately and static filters handle the request. - Host-Level Evaluation —
DynamicHostRuleFiltering.evaluateCellZY()checks bitmap rules from most specific to least specific. If it returns block (1) or allow (2), the decision is final. - URL-Level Firewall — If host-level returns noop (3), the engine consults
µb.permanentFirewallandsrc/js/url-net-filtering.jsfor pattern matches.
This cascade ensures that broad rules can be overridden by specific exceptions, and that users can disable the entire system without affecting static filter operation.
Practical Implementation Examples
The following code examples demonstrate how to interact with the three blocking levels programmatically:
// Level 1: Toggle the master switch
µb.sessionSwitch = true; // Enable dynamic filtering
µb.sessionSwitch = false; // Disable all dynamic rules
// Level 2: Add a host-level rule (block all 3rd-party scripts)
µb.dynamicFilteringDefault.push('* * 3p-script block');
µb.permanentFirewall.fromString(
µb.dynamicFilteringDefault.join('\n')
);
// Level 3: Add a URL-level rule (allow specific tracker)
const urlRule = '||tracker.example.com/collect.js$script,allow';
µb.permanentFirewall.fromString(urlRule, true); // true = append
// Debug: Inspect current rule set
console.log(µb.dynamicFilteringDefault.join('\n'));
Summary
- Master Switch: The global Boolean (
µb.sessionSwitch) that enables or disables the entire dynamic filtering engine insrc/js/dynamic-net-filtering.js. - Host-Level Rules: Bitmap-based filtering using
DynamicHostRuleFiltering.evaluateCellZY()to match source/destination hostnames and request types with numeric return codes (1=block, 2=allow, 3=noop). - URL-Level Rules: Pattern-matched string rules stored in
µb.permanentFirewalland parsed bysrc/js/url-net-filtering.jsfor exceptions requiring full URL wildcards. - Evaluation Order: Master switch → Host-level bitmap → URL-level patterns, with early termination when a definitive block or allow decision is reached.
Frequently Asked Questions
What is the difference between host-level and URL-level dynamic filtering?
Host-level rules operate on domain names and request types using an efficient bitmap system in src/js/dynamic-net-filtering.js, making them fast for broad policies like blocking all third-party scripts. URL-level rules match full URL patterns including wildcards via src/js/url-net-filtering.js, providing precision for exceptions like allowing a specific image from a blocked domain. Host rules are evaluated before URL rules, so URL rules can override host-level "noop" decisions but not explicit host-level blocks or allows.
How does the master switch affect static filter lists?
The master switch (µb.sessionSwitch) only controls the dynamic filtering engine defined in src/js/dynamic-net-filtering.js. When disabled, uBlock Origin ignores all dynamic host and URL rules, falling back entirely to static filter lists (EasyList, EasyPrivacy, etc.). Static filters operate independently and continue blocking content based on their own syntax and rules regardless of the dynamic filtering master switch state.
Can dynamic filtering rules override static filter decisions?
Yes, but only when dynamic filtering returns a definitive allow (2) or block (1) decision. According to the evaluation flow in DynamicHostRuleFiltering.evaluateCellZY(), if dynamic filtering returns "noop" (3), the decision passes to static filters. An explicit "allow" from dynamic filtering (particularly at the URL level) can unblock a request that static filters would otherwise block. Conversely, a dynamic "block" prevents the request regardless of static filter allow rules.
What request types are supported in host-level dynamic filtering?
Host-level rules support granular request types defined in the typeBitOffsets table within src/js/dynamic-net-filtering.js. These include script, image, stylesheet, object, xmlhttprequest, subdocument, ping, websocket, other, as well as composite types like 1p-script (first-party script), 3p-script (third-party script), 3p-frame (third-party frame), and 3p (all third-party requests). Each type occupies specific bit positions in the rule bitmap to enable efficient evaluation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →