Setting name: "defaultFiltering"
Type: string
Valid values: "none", "basic", "optimal", "complete"
Additionally, fix default "basic" mode toggling back to "optimal"
upon extension restart when uBOL has broad host permissions. The
default mode will toggle automatically only when there is a change
in broad host permissions status.
The quoted email below was sent to ubo-security at raymondhill dot net:
=====
Dear Raymond,
I am writing to report a potential Regular Expression Denial of Service (ReDoS)
vulnerability in the 1p-filters.js script of uBlock Origin. The vulnerability
occurs due to the use of the regular expression /\s+$/, which is used to remove
trailing whitespace. This issue can lead to a denial of service when processing
strings with a large number of trailing spaces, potentially causing a browser to
freeze.
Affected file(s)
js/1p-filters.js
Vulnerable pattern(s)
Lines 131 and 167: /\s+$/
Description of the issue
The regular expression /\s+$/ is applied to remove trailing whitespace in user‑
provided content. However, when the content has a large number of spaces
(e.g., ~100,000), this pattern causes excessive backtracking in the regular
expression engine, resulting in performance degradation and UI freezing. This is
a classic ReDoS attack vector.
Steps to reproduce
1. Open the uBlock Origin dashboard and navigate to the My filters tab.
2. Run the following code in the browser's DevTools Console or as a bookmarklet.
3. Observe the UI freezing for several seconds or even longer, depending on the
number of spaces used.
PoC (Proof of Concept)
/**
* poc.js — triggers ReDoS in 1p-filters.js
* Expected: <1 ms; Actual: several seconds – UI freeze
*/
(() => {
const payload = " ".repeat(100000) + "!"; // 100,000 spaces + sentinel
const run = () => {
if (!window.cmEditor) {
console.error("cmEditor not ready");
return;
}
// Inject payload into the editor
cmEditor.setValue(payload);
console.time("ReDoS");
// Call the vulnerable function (mirroring getEditorText)
cmEditor.getValue().replace(/\s+$/, '');
// Alternatively, simulate a realistic user flow:
// document.querySelector('#userFiltersApply').click();
console.timeEnd("ReDoS");
};
if (document.readyState === "complete") {
run();
} else {
window.addEventListener("load", run, { once: true });
}
})();
Impact
This issue can significantly degrade the user experience, causing the page to
become unresponsive. If an attacker can inject this malicious string into the
page (for example, through XSS or other attacks), it could lead to a denial of
service (DoS). This vulnerability can be triggered repeatedly, causing the
browser to hang indefinitely.
Suggested fix
The issue can be mitigated by replacing /\s+$/ with a more efficient solution,
such as a look‑behind assertion /(?<=\S)\s+$/ (available in modern browsers)
which ensures no backtracking occurs, or using trimEnd() for legacy support:
// Example of using look-behind:
cmEditor.setValue(text.replace(/(?<=\S)\s+$/, '') + '\n\n');
// Alternatively, using trimEnd():
cmEditor.setValue(text.trimEnd() + '\n\n');
Additional information
If required, I am happy to assist in testing or provide more information.
Please feel free to contact me for further clarification.
Best regards,
[redacted]
=====
As discussed with filter list maintainers.
* @scriptlet trusted-create-element
*
* @description
* Element(s) from a parsed HTML string are added as child element(s) to a
* specific parent element in the DOM.
*
* @param parent
* A CSS selector identifying the element to which created element(s) will be
* added.
*
* @param html
* An HTML string to be parsed using DOMParser, and which resulting elements
* are to be added as child element(s).
*
* @param duration
* Optional. If specified, the time in ms after which the added elements will
* be removed. No removal will occur if not specified.
In Firefox, scriptlets are dynamically registered as content scripts
to ensure they execute in a timely manner.
The race condition could lead to scriptlet injection failing at
browser launch time in Firefox when the setting "Suspend network
activity until all filter lists are loaded" had been disabled[1],
even after forcing a page reload. Causing the filter lists to
reload would make the issue go away.
[1] Default is enabled in Firefox and it is strongly advised to NOT
change this.
Related issue:
https://github.com/uBlockOrigin/uBOL-home/issues/326
uBOL now asks broad host permissions by default. Users can still
choose narrow host permissions by using their browser's controls
for this.
For instance in Chromium, those host permissions controls are found
in the "Site access" section in the detailed view of an extension.
One can set "Site access" to "On click" to revoke broad host
permissions, and grant host permissions to only specific site.
In such mode, uBOL will still block through the DNR API, but no
cosmetic or scriptlet filtering will occurs, as these requires
permission to "read and change data" on websites for which higher
filtering mode is desired.
Some browsers do not automatically grant broad host permissions
even when an extension asks for broad permissions at install time,
and going forward all browsers will likely adopt this approach, and
thus it no longer made sense for uBOL to default to no broad hosts
permissions at install time, especially given this leads to issues
with no solution -- issues solved with the new approach (e.g. like
the ability to deploy uBOL in Optimal mode by default).