Skip to content

Latest commit

 

History

History
1474 lines (1118 loc) · 72.8 KB

CHANGELOG.md

File metadata and controls

1474 lines (1118 loc) · 72.8 KB

Scriptlets and Redirect Resources Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Added

  • XPath expressions support in trusted-click-element selectors, wrapped in xpath(), e.g. xpath(//button[contains(text(), "Accept")]), also combined with >>> combinator, e.g. div#host >>> xpath(descendant-or-self::button). Absolute paths after >>> are evaluated against the document in Chromium-based browsers before version 146, so e.g. xpath(//button) selects nothing there, and relative paths with descendant-or-self:: axis should be used instead. Invalid XPath expressions are logged once and the scriptlet exits. Errors which occur only on evaluation of page elements, e.g. a type error in a predicate like //button[count(1)], may not be detected and are not logged, and such expression selects nothing while the error occurs, e.g. while there is a button on the page, or after >>> only the elements of top-level elements of the shadow root without the error.
  • isTrusted:all in extraMatch of trusted-click-element to spoof isTrusted for all click-related events on the page, including the page's own ones, e.g. a click which a page handler dispatches on another element in response, similarly to the behavior before #582, but trusted events are passed unchanged, and all listeners of an event receive the same proxy. Only listeners added by addEventListener() after the scriptlet has run receive spoofed events of the page; inline on... handlers receive spoofed events only on the clicked element during an event of the scriptlet of the same type, including the page's own events of that type dispatched on it meanwhile, so other page events may reach them unspoofed. It is enabled for the whole page, including the clicks of other rules, and may break the page, e.g. its guards which compare events, or its code which passes events to native methods, so use it only if the page does not accept the clicks of the scriptlet otherwise. It can be combined with other conditions in any order, but for compatibility with older versions of the scriptlet, it should be the first or the only condition, e.g. isTrusted:all, !cookie:consent. Older versions ignore it only there, but take it after another condition as a part of that condition's value, e.g. with !cookie:consent, isTrusted:all they click regardless of the consent cookie, and with containsText:Accept, isTrusted:all they never click.

Changed

  • Minimum supported Microsoft Edge version is now Edge Chromium 80.
  • trusted-click-element spoofs isTrusted by default only for its own clicks, and for the clicks which labels forward from them to their controls, as one event shared by all listeners, instead of all click-related events on the page, which replaced the page's own events with proxies and broke popup opening-event guards #582. The spoofed event is still not the same object as window.event. If a rule needs the page's own events to be spoofed as well, e.g. a click which a page handler dispatches in response, isTrusted:all should be added to its extraMatch, as the first condition for compatibility with older versions. It is needed as well for a click forwarded by a label in a closed shadow root which wraps the slot of the clicked element, as such label is not found by default. If an older version of trusted-click-element runs on the same page as well, e.g. in another AdGuard product, and this version hooks event listeners first, the clicks of the older version are not spoofed for event listeners until the page is reloaded, unless a rule of this version has isTrusted:all. If the page has sealed EventTarget.prototype before the scriptlet runs, isTrusted is not spoofed for event listeners, which is logged, as the rules cannot share the hook then, but the elements are still clicked.
  • trusted-click-element validates its selectors once and exits if any of them is invalid, logging it with the reason, instead of throwing an error after hooking event listeners and attachShadow, or on each DOM change. So no element is clicked then, including the ones matched by valid selectors before the invalid one, e.g. a selector with a pseudo-class which is not supported by the browser.
  • stack of trusted-json-set is matched against the stack trace of the intercepted call without the frames of the scriptlet itself, which it contained before. So stack values which matched these frames no longer match the calls from other scripts, e.g. inlineScript if the scriptlet is injected as an inline script. Also, a call which does not match stack is not processed at all, e.g. a JSON string returned by it is not parsed and serialized again, which removed its formatting before.
  • trusted-replace-outbound-text with stack calls hit only for the calls which match stack.
  • json-prune-xhr-response and trusted-json-set-xhr-response intercept setRequestHeader(), getResponseHeader(), getAllResponseHeaders() and abort() of XMLHttpRequest.prototype as well, instead of setRequestHeader() of each matched object, which no longer gets it as its own property, unless it has another method, which is wrapped then, e.g. its own one assigned by the page, or the hook of another rule of these scriptlets. load and loadend of a modified response are dispatched as ProgressEvent, instead of Event, with the progress of the original response for an asynchronous request, as by a native request, and with zero length otherwise.
  • stack of trusted-json-set-fetch-response, json-prune-fetch-response, and of json-prune for Response.prototype.json() is matched against the stack trace of the call of fetch() or json() without the frames of the scriptlet itself, which it contained before, as it was matched after the response was awaited. So stack values which matched these frames no longer match the calls from other scripts, e.g. inlineScript if the scriptlet is injected as an inline script. Also, in Chromium-based browsers, an async function which awaits the response no longer matches it if it is not in the stack when fetch() or json() is called, e.g. if the request is sent by a timer. In logging mode of json-prune-fetch-response and json-prune, stack is still not matched, and the stack trace of the call is logged with the content.
  • Documented that the stack parameter of abort-on-stack-trace scriptlet supports regular expressions #393.

Deprecated

  • Edge Legacy support.

Removed

Fixed

  • xml-prune evaluating an XPath expression without the closing parenthesis with its last character dropped, e.g. xpath(//*[name()="Period"]/@duration as //*[name()="Period"]/@duratio, instead of logging it as invalid.
  • Fetch-based scriptlets failing to match requests when fetch receives a URL object #577.
  • Scriptlets which re-apply themselves on DOM changes, e.g. remove-attr and remove-class, no longer stop doing it after an error thrown on a DOM change, e.g. by the page for an element. Also, remove-attr, remove-class, remove-in-shadow-dom and hide-in-shadow-dom log an error thrown for an element once, and continue with other elements, including ones added later, even if the error is thrown when the rule is applied.
  • Infinite mutation loop and repeated logging when several non-conflicting set-attr or trusted-set-attr rules are applied on the same page: the attribute is no longer re-set, and hit is not called, if it already has the required value. Also, set-attr logs a missing attribute to copy the value from once for each element until the attribute is found, even if the element already holds the copied value. An error thrown for an element, e.g. by the page, is logged once for the element and does not stop setting the attribute on other elements, including ones added later, or prevent hit for changed elements. An invalid name of the attribute to copy the value from, e.g. [data a] or [], is logged once as an invalid value, instead of setting the attribute to null on each matched element.
  • Infinite mutation loop between several non-conflicting href-sanitizer rules, and hit called on each DOM change: href is no longer re-set, and hit is not called, if the link, including SVG <a> element, already points to the sanitized URL. Also, href-sanitizer logs invalid arguments only once, logs a failure to sanitize a link only once until its href or the value taken from the link is changed, or the URL resolved from it if the failure depends on the document base URL, and does not log a link sanitized by the rule as a failure, e.g. one without the URL parameter, or a base64 string which is not a URL if another one in the same value is decoded. An error thrown for a link, e.g. by the page, is logged once and does not stop sanitizing of other links.
  • href-sanitizer resolving relative URLs against the page URL or its origin instead of the document base URL, e.g. removeHash and removeParam transforms rewrote a path-relative link to a wrong URL, or a link within the page, e.g. #comments, to another page.
  • Infinite mutation loop between an href-sanitizer rule and another one which changes the URL set by it, e.g. a rule with link text and a rule with removeParam:utm_source on the same link, or a rule with an attribute and a rule with ?url which unwraps the redirect set by the first one. Rules share their last actual write on the affected link, without a window registry or HTML attributes, so page edits of the link are still corrected, including ones which another rule has changed.
  • href-sanitizer not sanitizing SVG <a> element by a URL parameter, e.g. ?url.
  • removeHash and removeParam transforms of href-sanitizer not setting the URL found in the link text, attribute or URL parameter if there is nothing to remove from it, as it is done without a transform.
  • href-sanitizer setting link text which is not a URL as a relative URL or as a broken URL: link text is set only if it is an absolute URL or a path without whitespaces, e.g. not Click here, Download, ? or https://example.org/ (external), and not if a tab or newline is between its words, e.g. between the URL and the title of a card, rather than next to a URL delimiter, e.g. /. Also, a value of only whitespaces is not set, and neither is a placeholder hash, i.e. # or #!, unless it is href of the link.
  • href-sanitizer decoding + in the URL parameter as a whitespace if the parameter is a URL which is not encoded, e.g. ?url=https://example.org/c++/docs or ?url=https%3A//example.org/c++/docs.
  • href-sanitizer not decoding base64 string in a relative href, in href within the page, e.g. #<base64>, or in the hash if the query has no base64 encoded URL, e.g. https://example.org/?ref=1#<base64>.
  • href-sanitizer accepting any transform starting with removeParam, e.g. removeParams, which removed all parameters.
  • href-sanitizer unwrapping nested redirects in the URL parameter or base64 encoded ones only one by one on each DOM change; now up to 10 of them are unwrapped at once, and the rest right after that, as long as the link is still matched by the selector. Relative URL in the nested redirect, e.g. a parameter of the target with the same name, is not followed and not logged, since it is relative to the redirect, except for a scheme-relative one, e.g. //example.org/.
  • Repeated logging on each DOM change by remove-attr if its selector matches elements without the attribute: hit is called only if some attribute has actually been removed. Also, invalid selector is logged only once.
  • Infinite mutation loop between several hide-in-shadow-dom rules whose targets are light DOM children of shadow hosts, and hit called on each DOM change: already hidden elements are no longer re-hidden, and hit is called only if some element has actually been hidden.
  • hide-in-shadow-dom and remove-in-shadow-dom not working if baseSelector matches an element which is not a shadow host itself, e.g. a container of shadow hosts. Also, both scriptlets log an invalid selector or baseSelector instead of throwing an error.
  • Invalid selector logged on each DOM change by remove-class, set-attr and trusted-set-attr, as well as invalid attribute name by set-attr and trusted-set-attr: they are now validated and logged only once.
  • remove-class and remove-attr not removing classes or attributes whose names are not valid CSS identifiers, e.g. md:hidden or x-on:click, if no selector is specified.
  • trusted-click-element splitting selectors by commas inside pseudo-classes, e.g. :is(.accept, .agree), by commas inside quoted attribute values, e.g. [title="Accept, agree"], and by escaped commas, e.g. #accept\,agree, which made such selectors invalid. Also, >>> inside quoted strings or CSS comments, e.g. in [title=" >>> "], is no longer taken for the shadow combinator.
  • trusted-click-element ignoring containsText when it finds an element again because the found one was removed from DOM before the click, which could click another element matching the selector.
  • trusted-click-element not clicking an element if containsText, or the key of a cookie condition, is a regexp with g or y flag, as each next check started from the end of the previous match, e.g. cookie:/consent/g=/yes/ did not match consent_a=no; consent_b=yes.
  • trusted-click-element clicking next elements of the sequence if a previous element was removed from DOM before the click and could not be found again.
  • trusted-click-element not clicking elements after an empty selector, e.g. #accept in #settings,, #accept, and not calling hit if there is a trailing comma, e.g. in #accept,: empty selectors, and ones with only a CSS comment, are skipped.
  • trusted-click-element hooking event listeners and attachShadow even when it exits early because of invalid timeout, delay or reload values or unmatched extraMatch conditions #582.
  • trusted-click-element failing to remove or deduplicate listeners shared across event targets, registered with non-boolean capture values or with options which return a different value on each read, and failing to remove a listener registered before the scriptlet ran if the same listener was also added after it #582.
  • trusted-click-element not finding elements in a closed shadow root attached with options which return a different mode on each read.
  • trusted-click-element not clicking next elements of the sequence if a React click handler of the page throws, and clicking the element again when the sequence is continued, with the error not logged but reported as an unhandled rejection: the error is logged once and the next elements are clicked.
  • trusted-click-element silently not spoofing isTrusted, or not tracking shadow roots attached later, if another script has made addEventListener(), removeEventListener() or attachShadow() read-only: it is logged now, and elements which can still be found are clicked.
  • trusted-click-element with >>> combinator observing shadow roots attached after it has found all elements or its observer has timed out, which changed an attribute of the html element on each of their changes and so woke up all observers of the page for its whole lifetime.
  • trusted-click-element throwing when inline on* handlers or React handlers set cancelBubble or returnValue on a scriptlet click #582.
  • trusted-click-element restoring inline on* handlers of the clicked element that the page replaced or cleared during the click #582.
  • trusted-click-element exposing a bound constructor on spoofed events and an untrusted nativeEvent to React handlers #582.
  • trusted-click-element passing an untrusted event to an inline on... handler of the clicked element which the page assigns during an earlier event of the click, e.g. onclick set on mousedown.
  • trusted-click-element reporting outdated isDefaultPrevented() and isPropagationStopped() to React handlers if the default action or propagation is changed through nativeEvent, returnValue or cancelBubble.
  • trusted-json-set modifying a native Promise returned by the intercepted method, e.g. Response.prototype.json, instead of the value it is fulfilled with #585. The value is modified now, and a new promise of it is returned, while a rejection is passed through. In logging-only mode, the value is logged, and the original promise is returned. Promises of polyfills or libraries which replace window.Promise, e.g. zone.js, are not supported. stack is matched when the method is called, so it works for such values as well. Also, the intercepted method is no longer called again if it throws an error.
  • stack of trusted-replace-outbound-text, trusted-suppress-native-method, json-prune-xhr-response and trusted-json-set-xhr-response not matching the function which calls the intercepted method in browsers whose stack traces have no error message line, e.g. Firefox, as the frame of that function was removed as the scriptlet's own one.
  • stack of trusted-json-set-fetch-response, json-prune-fetch-response, and of json-prune for Response.prototype.json(), not matching a function which returns the promise of fetch() or json(), as it was matched after the response was awaited, when the function was no longer in the stack. It is matched when the method is called now, and the calls which do not match it are passed through as is, so json-prune-fetch-response no longer calls hit for them.
  • trusted-json-set-fetch-response and json-prune-fetch-response sending the request again if it fails, e.g. a POST request, or if its response cannot be cloned. The rejection of the request is passed to the page now, and the response is returned as is if it cannot be cloned.
  • trusted-replace-outbound-text not modifying any content after the intercepted method is called from a function which does not match stack, e.g. by another script of the page, or after it throws an error, e.g. JSON.stringify of an object with a circular reference.
  • trusted-replace-argument calling the intercepted method or constructor again if it throws an error, so its side effects were repeated, and the second call could even succeed.
  • trusted-replace-argument throwing an error to the page instead of calling the intercepted method if null or undefined is thrown while the arguments are processed, e.g. by a conversion of an argument to a string, or by Error replaced by the page while the stack trace for stack is created. The method is called with the original arguments now.
  • trusted-replace-argument not matching an object argument by its string value if it cannot be serialized as JSON, and the error of it cannot be converted to a string to be logged, e.g. Object.create(null) thrown by its toJSON(). The argument and the error are no longer converted to strings to be logged.
  • call-nothrow throwing an error to the page if the intercepted method throws null or undefined, as getting the message of such error threw another one.
  • trusted-suppress-native-method throwing an error to the page and no longer intercepting the next calls after an error while a call is matched, e.g. thrown by a getter of an argument, or by Error replaced by the page while the stack trace for stack is created. Such call is not suppressed now.
  • trusted-json-set and trusted-json-set-fetch-response processing a JSON string or response body again as line-delimited JSON if its modification fails, e.g. as the modified value cannot be serialized, so it was modified again, and hit could be called twice. Such string or response is returned unchanged now.
  • JSONPath rules of json-prune and json-prune-fetch-response throwing an error to the page, e.g. from JSON.parse() or by rejecting the promise of fetch(), if null or another value without a message is thrown while the content is processed, e.g. by a getter of the page, as getting the message of it to log it threw another error. The same applies to json-prune, json-prune-fetch-response, evaldata-prune and trusted-prune-inbound-object while messages are logged, if such value cannot be converted to a string, e.g. Object.create(null).
  • trusted-json-set not modifying anything, even without stack, if the stack trace cannot be read, e.g. because of Error.prepareStackTrace of the page or Error replaced by it. Only the rules with stack are not applied then. The same applies to JSONPath rules of json-prune, json-prune-fetch-response and trusted-json-set-fetch-response, and to trusted-json-set-fetch-response rules with verbose. trusted-json-set no longer reads the stack trace at all for rules without stack, except in logging-only mode or with verbose.
  • json-prune-xhr-response and trusted-json-set-xhr-response throwing an error from XMLHttpRequest.send(), so the request was not sent at all, even without stack, if the stack trace cannot be read, e.g. because of Error.prepareStackTrace of the page or Error replaced by it. Only the rules with stack are not applied then, and the request is sent as is. They no longer read the stack trace at all for rules without stack, except in logging mode of json-prune-xhr-response or with verbose of trusted-json-set-xhr-response.
  • json-prune, json-prune-fetch-response, evaldata-prune and trusted-prune-inbound-object in logging mode throwing an error to the page, e.g. from JSON.parse(), if the stack trace cannot be read, e.g. because of Error.prepareStackTrace of the page or Error replaced by it. Also, the content matched by obligatoryProps was not logged then, also by json-prune-xhr-response. The content is logged without the stack trace now.
  • json-prune, evaldata-prune and trusted-prune-inbound-object in logging mode throwing an error to the page, e.g. from JSON.parse() or eval(), or instead of calling the intercepted method, if the content cannot be serialized to be logged, e.g. a circular object or a too deeply nested one. Also, json-prune-fetch-response rejecting the promise of fetch() then, json-prune-xhr-response returning the text of such response instead of its object for responseType json, and the content matched by obligatoryProps not being logged then. Such content is logged only as an object now.
  • trusted-json-set, trusted-json-set-fetch-response and trusted-json-set-xhr-response with verbose not modifying the content if it cannot be serialized to be logged, e.g. a too deeply nested JSON response or an object whose toJSON() throws. Such content is logged only as an object now.
  • json-prune-xhr-response and trusted-json-set-xhr-response not firing load for the second matched request of a reused XMLHttpRequest object, as the props of its response could not be defined again, and returning the props of the previous response, e.g. readyState and response, for a request on such an object which is not matched. Also, for such an object, sending the headers of each request again with the next ones, forging a request with the method and URL of the previous open() if the object is opened again before it is sent, and delivering the response of a request after the object is opened again or the request is aborted by abort(), which dispatches the events of an aborted request now. Also, readystatechange is dispatched when such object is opened again, as by open() of a native object which is done.
  • json-prune-xhr-response and trusted-json-set-xhr-response dispatching the events of a modified response of a synchronous request after XMLHttpRequest.send() has returned, so the page could not use the response in its load listener right after send(). They are dispatched before send() returns now, as by a native request.
  • json-prune-xhr-response and trusted-json-set-xhr-response sending a request synchronously if it is opened without async, e.g. by open(method, url). Also, user and password passed to open() were not used for the request.
  • json-prune-xhr-response and trusted-json-set-xhr-response throwing an error from XMLHttpRequest.send() for each matched request if the page has replaced XMLHttpRequest after the scriptlet has run, e.g. by a library which wraps requests, as the forged request was created by it.
  • json-prune-xhr-response and trusted-json-set-xhr-response sending the request again if sending it fails, e.g. a synchronous POST request with a network error, so its side effects were repeated. The error is thrown to the page now, and the object is done with no response then, as a native one.
  • json-prune-xhr-response, trusted-json-set-xhr-response and trusted-replace-outbound-text, and JSONPath rules of json-prune, json-prune-fetch-response and trusted-json-set-fetch-response, throwing an error to the page if stack is an invalid regular expression, e.g. from XMLHttpRequest.send(), so the request was not sent, or from JSON.parse(), or rejecting the promise of fetch() or Response.prototype.json() with it. Such rules are not applied now, and the call is passed through. The same applies to trusted-replace-outbound-text if textToReplace is an invalid regular expression.
  • json-prune-xhr-response and trusted-json-set-xhr-response returning no response headers from getResponseHeader() and getAllResponseHeaders() of an intercepted XMLHttpRequest object, e.g. null for Content-Type, as the object is not sent itself. The headers of the response are returned now, as by trusted-replace-xhr-response #419.
  • json-prune-xhr-response, trusted-json-set-xhr-response, json-prune-fetch-response, call-nothrow, trusted-replace-outbound-text and trusted-suppress-native-method changing toString() of the intercepted methods, e.g. XMLHttpRequest.prototype.open.toString() or fetch.toString(), which returned the string of a native function without its name. It returns the original value now.
  • json-prune-xhr-response and trusted-json-set-xhr-response never completing a request whose response could not be modified, e.g. as logging a too deeply nested JSON response with verbose threw an error, or defined on the object, e.g. if the page has made it not extensible. The events of the response are dispatched now in both cases, with the original text of the response if it could not be modified, while the object keeps its state if the response could not be defined.
  • json-prune-fetch-response rejecting the promise of fetch() of a request which has succeeded, if its response could not be modified, e.g. as serializing a too deeply nested JSON response threw in browsers whose JSON.stringify() is recursive. The original response is returned now.
  • json-prune-xhr-response in logging mode returning a JSON response as a string, even if another responseType of the request is set, e.g. json, arraybuffer or blob. A response which is not JSON is still returned as a string.
  • json-prune calling then() of the promise of Response.prototype.json(), which the page may replace, to prune its value. Its own then() is still used only if Promise has been replaced before the scriptlet has run, e.g. by zone.js.
  • trusted-replace-outbound-text with stack throwing an error to the page instead of the result of the intercepted method if the stack trace cannot be read, e.g. because of Error.prepareStackTrace of the page or Error replaced by it. The result is returned unmodified then.
  • trusted-suppress-native-method, trusted-json-set, trusted-replace-argument, trusted-replace-outbound-text, trusted-prune-inbound-object and call-nothrow not intercepting methods of localStorage and sessionStorage, e.g. localStorage.setItem, in Firefox, and storing an item named after the method in the storage instead, e.g. setItem. The method is replaced in Storage.prototype now, unless the page has assigned its own method to the storage, e.g. in Chrome, and only its calls on the storage of the rule are processed, also the ones made through Storage.prototype.
  • isValidStrPattern helper not validating a regular expression pattern with flags, e.g. /foo(/i, so such a pattern was treated as valid and scriptlets failed when converting it to a regexp.

Security

2.5.1 - 2026-08-25

2.5.1-beta.1 - 2026-08-25

Changed

2.5.1-beta.0 - 2026-08-05

Added

  • Support of $now$, $currentDate$, and $currentISODate$ keywords used as a part of the value, not as a standalone value only, e.g. '{"count":1,"firstTime":$now$}'; more than one keyword may be used in the value. Applies to trusted-set-cookie, trusted-set-cookie-reload, trusted-set-local-storage-item, and trusted-set-session-storage-item scriptlets #573.
  • Support of $now$, $currentDate$, and $currentISODate$ keywords in argumentValue of trusted-json-set, trusted-json-set-fetch-response, and trusted-json-set-xhr-response scriptlets — as a whole value, as a part of it, and inside json: and replace: values, e.g. 'json:{"count":1,"firstTime":$now$}' #573.

2.5.0 - 2026-07-27

Added

  • json-edit, json-edit-xhr-response, and json-edit-fetch-response scriptlet aliases as uBO-compatible names for json-prune, json-prune-xhr-response, and json-prune-fetch-response respectively #566.
  • Dot-prefixed JSONPath auto-detection in resolveJsonSyntaxMode — expressions starting with . are now treated as JSONPath mode without explicitly passing mode=jsonpath #566.
  • trusted-prevent-xhr scriptlet, a trusted variant of prevent-xhr that supports passing arbitrary literal text as the XHR response body #417.
  • Expanded prevent-xhr randomize directive: added emptyObj, emptyArr, emptyStr, single-value length:N (e.g. length:50).
  • prevent-xhr and trusted-prevent-xhr now handle document and json XHR responseType values when intercepting matched requests.

Changed

  • Updated @adguard/agtree to v4.2.0.
  • UBO aliases for prevent-bab scriptlet and redirect.

Fixed

  • trusted-replace-argument — when replace: is used and the argument is not a string, the argument is no longer blindly overwritten with the replacement value; the replacement is applied to its string form and the original value and type are kept when the pattern does not match #570.
  • adjust-setTimeout, adjust-setInterval, prevent-setTimeout, prevent-setInterval, and prevent-requestAnimationFrame now handle callbacks with a modified prototype chain: isValidCallback uses a typeof check instead of instanceof Function, and callback stringification uses the native Function.prototype.toString so that matchCallback matching and logging work for such callbacks and never throw #561.

2.4.3 - 2026-06-24

Added

  • setConfig and getConfig methods to googletagservices-gpt redirect #560.
  • Delay range matching for prevent-setTimeout and prevent-setInterval scriptlets. Supported formats: min-max, min-, -max, with ! prefix for inversion #467.

Changed

  • listenerToString helper now uses native Function.prototype.toString to prevent issues where websites redefine it #292.
  • prevent-fetch now supports a structured responseConfig argument for overriding synthetic response fields such as ok, redirected, status, statusText, and extended type values #529.

Fixed

  • trusted-replace-xhr-response response headers (getResponseHeader, getAllResponseHeaders) now return the correct values on intercepted XHR objects #419.
  • Maximum call stack size exceeded error when trusted-json-set or trusted-replace-argument is called with method used inside scriptlet #565.
  • Infinite loop in getRecursiveCandidates in json-path-utils #563.
  • Missing google.ima.dai.api.ui, google.ima.dai.api.customUi surfaces and the default StreamRequest.ui container in the google-ima3-dai redirect.
  • Missing google.ima.dai.api.StreamRequest.StreamFormat object to the google-ima3-dai redirect.
  • Redirect resources with a .ts extension are now converted to .js.

2.4.2 - 2026-04-24

Added

  • Scriptlets release version for google-ima3-dai.

2.4.1 - 2026-04-23

Added

  • google-ima3-dai redirect resource and scriptlet #239.

Changed

2.4.0-beta - 2026-04-21

Added

  • New mode parameter to all json-prune and trusted-json-set related scriptlets, which allows to specify the way of pruning JSON objects #522.
  • Line-delimited JSON processing in trusted-json-set related scriptlets #522.
  • $remove$ value to all trusted-json-set related scriptlets, which allows removing specific properties #522.
  • Support for JSONPath in json-prune, json-prune-fetch-response, json-prune-xhr-response, trusted-json-set, trusted-json-set-fetch-response and trusted-json-set-xhr-response scriptlets #522.

Changed

  • trusted-json-set now supports method-only logging, filtered log-only output, JSONPath-based log-only filters, and verbose logs only when a write actually happens #308.
  • log-addEventListener scriptlet: added new optional noProtect parameter, improving compatibility with other scriptlets that need to override addEventListener #551.
  • Updated @adguard/agtree to v4.1.0-beta.

Fixed

  • Logging original object in trusted-json-set scriptlet, previously original and modified object were pointing to the same reference, so the same content was logged, now deep copy is created for original object #308.
  • trusted-click-element no longer throws when event handlers set cancelBubble on spoofed events #555.

v2.3.1 - 2026-03-24

Changed

Fixed

  • disable-newtab-links not preventing clicks when the element has its own click handler added via addEventListener #483.

v2.3.0 - 2026-03-18

Added

  • New value to set-cookie and set-cookie-reload scriptlets: all #501.
  • New value to set-cookie and set-cookie-reload scriptlets: mandatory #518.
  • New value to set-cookie and set-cookie-reload scriptlets: declined #552.
  • trusted-json-set, trusted-json-set-fetch-response and trusted-json-set-xhr-response scriptlets #308.
  • freewheel-admanager redirect resource and scriptlet #401.
  • getCreativeId method to Ad class in google-ima3 redirect #515.

Changed

  • trusted-click-element now passes synthetic-like event objects to React handlers and supports clickType:native in extraMatch to force native click #554.
  • Added interceptChainProp helper to share intermediate chain property access logic across abort-on-property-read, abort-on-property-write, abort-on-stack-trace, abort-current-inline-script, debug-on-property-write, debug-on-property-read, debug-current-inline-script and log-on-stack-trace scriptlets #513.
  • prevent-window-open now checks all parameters #549.
  • Updated @adguard/agtree to v4.0.2.

Fixed

  • prevent-fetch — do not use modifyResponse on redirected requests #545.
  • issue with assigning window to property which was not set in abort-on-property-read, abort-on-property-write, abort-on-stack-trace, abort-current-inline-script, debug-on-property-write, debug-on-property-read, debug-current-inline-script and log-on-stack-trace scriptlets #513.

v2.2.16 - 2026-02-19

Added

  • prevent-navigation scriptlet to prevent navigation to another URL, or reload website #532.
  • prevent-constructor scriptlet to prevent constructor calls like new Promise() or new MutationObserver() #461.
  • remove-request-query-parameter scriptlet to remove query parameters from fetch and XMLHttpRequest requests #329.
  • Trusted Types API support in trusted-create-element scriptlet #507.
  • Trusted Types API support in Firefox #528.

Changed

  • prevent-addEventListener scriptlet: added new optional noProtect parameter, improving compatibility with other scriptlets that need to override addEventListener #550.
  • Updated @adguard/agtree to v4.0.1.

Fixed

  • prevent-xhr scriptlet, responseURL is now set at readyState 2, and the first state is skipped when onreadystatechange is assigned after xhr.open() #485.
  • Anti-adblock detection in spoof-css scriptlet by using cloaked bound functions instead of Proxies #422.
  • Response corruption in trusted-replace-fetch-response and trusted-replace-xhr-response scriptlets when URL pattern matches but content pattern does not #486.
  • XHR handling in trusted-replace-xhr-response and xml-prune scriptlets:
    • added withCredentials to forged requests,
    • fixed duplicate headers when multiple scriptlets are used,
    • used ProgressEvent for load and loadend events #486.
  • XHR scriptlet bypass vulnerability in trusted-replace-xhr-response, prevent-xhr, and xml-prune scriptlets where setting xhr.shouldBePrevented = false could disable the scriptlet #386.
  • Parsing of regexp patterns containing pipe | character in signatureStr arg of trusted-suppress-native-method scriptlet #473.
  • Stack matching in set-constant and trusted-set-constant scriptlets — now checked at property access time instead of scriptlet initialization #500.
  • Cloudflare captcha broken when >>> combinator is used in trusted-click-element scriptlet #491.

v2.2.15 - 2026-01-22

Added

  • Support for React elements that don't respond to native clicks in trusted-click-element scriptlet #542.

Changed

Fixed

  • Do not throw error on null event type in prevent-addEventListener scriptlet #539.

v2.2.14 - 2025-12-16

Added

  • prevent-innerHTML scriptlet #488.
  • Ability to configure observer timeout for trusted-click-element scriptlet with a new observerTimeout parameter #400.
  • Support for window.Fingerprint variable in fingerprintjs2 redirect (and scriptlet as well since it is an alias for redirect) #541.

Changed

v2.2.13 - 2025-11-25

Added

  • New value to set-cookie and set-cookie-reload scriptlets: denied #512.

Changed

Fixed

  • Determination of string values more precisely for trusted-set-constant scriptlet #499.
  • Support for negative priority suffix in UBO redirects rules.

v2.2.12 - 2025-11-12

Changed

v2.2.11 - 2025-10-17

Changed

v2.2.10 - 2025-09-11

Added

  • -base64 as an alias of base64decode in href-sanitizer scriptlet #493.

Changed

v2.2.9 - 2025-08-14

Added

  • trusted-replace-argument scriptlet #405.

Fixed

  • Incorrectly escaped quotes in trusted-replace-node-text scriptlet #517.
  • TrustedScriptURL in prevent-element-src-loading scriptlet #514.
  • Fix scriptlets compilation error in Safari 15 due to unsupported regex lookbehind #519.

v2.2.8 - 2025-07-08

Added

  • UBO aliases ubo-nobab, nobab, and bab-defuser for prevent-bab AdGuard scriptlet.

Changed

Fixed

  • trusted-set-cookie-reload scriptlet infinite page reloading when cookie with time keyword is used #489.

v2.2.7 - 2025-06-04

Changed

Fixed

  • json-prune scriptlet to properly handle null values while checking specified key in object #504.

v2.2.4 - 2025-05-23

Changed

Fixed

  • spoof-css scriptlet — incorrect DOMRect setting #498.

v2.2.1 - 2025-05-21

Fixed

  • Trusted types bundle.

v2.2.0 - 2025-05-21

Added

  • New values to set-cookie and set-cookie-reload scriptlets: emptyArr, emptyObj #497.
  • Ability to set random response content in prevent-fetch scriptlet #416.
  • Ability to choose CSS injection method in inject-css-in-shadow-dom scriptlet #477.
  • TypeScript types for CoreLibs provided ContentScriptApi.
  • Trusted Types API utility — PolicyApi.

Changed

  • Improved docs for json-prune, xml-prune and trusted-prune-inbound-object scriptlets #392.
  • Updated @adguard/agtree to v3.1.5.

Fixed

  • Escaping quotes in trusted-replace-node-text scriptlet #440.
  • trusted-suppress-native-method scriptlet, isMatchingSuspended was not reset when the stack does not match, so in some cases given method was not prevented #496.

v2.1.7 - 2025-04-03

Changed

Added

  • Ability in prevent-addEventListener scriptlet to match specific element and updated log-addEventListener scriptlet to log target element #480.

v2.1.6 - 2025-03-06

Fixed

  • Incorrectly removing content from parsed array when using the json-prune scriptlet #482.

v2.1.5 - 2025-02-28

Changed

Added

  • Ability in json-prune scriptlet to match key with specific value and remove array/object if it contains specific item #183.

Fixed

  • prevent-eval-if and prevent-bab scriptlets, now eval.toString() call returns original value #481.

v2.1.4 - 2025-01-20

Changed

  • ESM-only bundle.
  • trusted-click-element scriptlet, now when containsText is used then it will search for all given selectors and click on the first element with matched text #468.

Fixed

  • Issue with metrika-yandex-tag redirect when it's used as a scriptlet #472.
  • Issue with trusted-click-element scriptlet when delay was used and the element was removed and added again before it was clicked #391.

v2.0.1 - 2024-11-13

Added

  • prevent-canvas scriptlet #451.
  • Trusted Types API support in trusted-replace-node-text scriptlet #457.
  • parentSelector option to search for nodes for remove-node-text scriptlet #397.
  • transform option with base64decode value for href-sanitizer scriptlet #455.
  • removeParam and removeHash values in transform option for href-sanitizer scriptlet #460.
  • New values to set-cookie and set-local-storage-item scriptlets: forbidden, forever #458.

Changed

  • Set response ok to false by prevent-fetch if response type is opaque #441.
  • Improve prevent-xhr — modify response #415.
  • Improve prevent-xhr — add missed events #414.
  • Source type instead of IConfiguration.
  • API structure. Validators, Converters, Scriptlets and redirects are now separate modules.
  • The minimum supported Safari version is now 13.
  • Updated @adguard/agtree to v3.0.0-alpha.1.

Removed

  • IIFE bundle.
  • UMD bundle.
  • Various conversion and validation functions including isAdgRedirectRule, isAdgRedirectCompatibleWithUbo, isUboRedirectCompatibleWithAdg, isAbpRedirectCompatibleWithAdg, convertUboRedirectToAdg, convertAbpRedirectToAdg, convertRedirectToAdg, and convertRedirectNameToAdg functions.

v1.12.1 - 2024-09-20

Added

  • Integrated @adguard/agtree library for working with rules, compatibility tables, validator and converter.

Fixed

  • Re-adding element on every DOM change in trusted-create-element scriptlet #450.
  • Setting cookie which name has special prefix __Host- or __Secure- by trusted-set-cookie and trusted-set-cookie-reload scriptlets #448.

v1.11.27 - 2024-08-29

Added

  • reload option for trusted-click-element scriptlet #301.
  • Support for matching line number in abort-on-stack-trace scriptlet when inlineScript or injectedScript option is used #439.
  • New values to set-cookie and set-cookie-reload scriptlets: checked, unchecked #444.
  • New values to set-local-storage-item and set-session-storage-item scriptlets: allowed, denied #445.
  • UBO aliases noop-vast2.xml, noop-vast3.xml, and noop-vast4.xml for correspondent AdGuard redirects.
  • New field uniqueId to scriptlet configuration, allowing scriptlets to be executed only once per context.

Changed

  • UBO alias noop-vmap1.0.xml for noopvmap-1.0 redirect is replaced by noop-vmap1.xml.

Fixed

  • Modifying RegExp.$1, …, RegExp.$9 values in log-on-stack-trace and abort-on-stack-trace scriptlets #384.

v1.11.16 - 2024-08-01

Added

  • trusted-set-session-storage-item scriptlet #426.
  • New values to set-cookie and set-cookie-reload scriptlets: essential, nonessential #436.
  • $currentISODate$ as a new possible value to set-cookie, set-cookie-reload, set-local-storage-item and set-session-storage-item scriptlets #435.

Fixed

  • Re-adding element after removing it in trusted-create-element scriptlet #434.
  • trusted-click-element scriptlet does not click on an element that is already in the DOM #437.

v1.11.6 - 2024-07-08

Added

  • New values to set-cookie and set-cookie-reload scriptlets: hide, hidden #433.
  • New values to set-local-storage-item and set-session-storage-item scriptlets: accept, accepted, reject, rejected #429.
  • Ability to log original and modified content in trusted-replace-node-text, xml-prune, m3u-prune, trusted-replace-fetch-response and trusted-replace-xhr-response scriptlets #411.

Changed

v1.11.1 - 2024-06-13

Added

  • trusted-dispatch-event scriptlet #382.
  • trusted-replace-outbound-text scriptlet #410.
  • Ability to click on the element with specified text in trusted-click-element scriptlet #409.
  • Ability to click element in closed shadow root in trusted-click-element scriptlet #423.
  • isRedirectResourceCompatibleWithAdg() method to check compatibility of redirect resources with AdGuard without needing the full rule text #420.

Deprecated

  • ruleText option in the IConfiguration.

Fixed

  • set-attr value cannot be set to minimum 0 and maximum 32767 possible value #425.

v1.10.25 - 2024-03-28

Added

  • trusted-suppress-native-method scriptlet #383.
  • json-prune-fetch-response scriptlet #361.
  • json-prune-xhr-response scriptlet #360.
  • href-sanitizer scriptlet #327.
  • no-protected-audience scriptlet #395.
  • The ability for prevent-fetch scriptlet to set cors as a response type #394.
  • The ability for trusted-click-element scriptlet to click inside open shadow doms #323.
  • Domain value for setting cookie scriptlets #389.
  • Multiple redirects can now be used as scriptlets #300:
    • amazon-apstag;
    • didomi-loader;
    • fingerprintjs2;
    • fingerprintjs3;
    • gemius;
    • google-analytics;
    • google-analytics-ga;
    • google-ima3;
    • googlesyndication-adsbygoogle;
    • googletagservices-gpt;
    • matomo;
    • metrika-yandex-tag;
    • metrika-yandex-watch;
    • naver-wcslog;
    • pardot-1.0;
    • prebid;
    • scorecardresearch-beacon.

Changed

  • Validation of scriptlet rules with no name and args for multiple scriptlet exception rules #377.
  • Cookie name is not encoded by cookie setting scriptlets #408.
  • Increased the possible numeric value up to 32767 for set-cookie and set-cookie-reload scriptlets #388.

Fixed

  • UBO→ADG conversion of $remove$ scriptlet param #404.
  • set-constant scriptlet not setting a constant over falsy values #403.

v1.10.1 - 2024-02-12

Added

  • call-nothrow scriptlet #333.
  • spoof-css scriptlet #317.
  • trusted-create-element scriptlet #278.
  • trusted-set-attr scriptlet #281.
  • Ability of set-attr to set an attribute value as a copy of another attribute value of the same element.
  • UBO alias for set-cookie-reload scriptlet #332.
  • New values t, f, necessary, required for set-cookie and set-cookie-reload #379.

v1.9.105 - 2023-12-25

Added

  • OmidVerificationVendor object to google-ima3 redirect #353.
  • ga.q (queued commands) to google-analytics redirect #355.

Fixed

  • addEventListener in EventHandler in google-ima3 redirect, now it binds context to callback #353.
  • AdDisplayContainer constructor in google-ima3 redirect, now it adds div element to container #353.
  • getInnerError method in google-ima3 redirect, now it returns null #353.

v1.9.101 - 2023-11-30

Added

  • emptyStr value for responseBody in prevent-fetch scriptlet #364.
  • setPrivacySettings() method to googletagservices-gpt redirect #344.
  • UBO alias noop.json for noopjson redirect.
  • Library version number to the exports AdguardBrowserExtension#2237.

Changed

  • prevent-fetch scriptlet, if responseType is set to opaque then now response body is set to null, status is set to 0 and statusText is set to '' #364.

v1.9.96 - 2023-11-15

Added

  • Regular expression support for removing items in set-local-storage-item and set-session-storage-item scriptlets #256.
  • Ability to set proxy trap in set-constant scriptlet #330.

v1.9.91 - 2023-11-13

Added

  • trusted-prune-inbound-object scriptlet #372.
  • New values to set-cookie scriptlet: on, off, accepted, notaccepted, rejected, allowed, disallow, enable, enabled, disable, disabled #375.
  • New values to set-local-storage-item and set-session-storage-item scriptlets: on, off #366.

Fixed

  • Setting proxy trap every time when property is accessed in set-constant scriptlet #380.
  • Issue with stack in evaldata-prune scriptlet #378.
  • Setting values to wrong properties in set-constant scriptlet #373.

v1.9.83 - 2023-10-13

Added

  • ABP alias for the log scriptlet.

Fixed

  • Issue with trusted-replace-fetch-response scriptlet in case if data URL was used and properties was set by Object.defineProperty to deceive scriptlet #367.
  • Adding the same header value in trusted-replace-xhr-response scriptlet when it is used multiple times for the same request #359.
  • Not pruning in m3u-prune scriptlet if file contains carriage return #354.
  • Not overriding value in set-constant (only partially, for cases where single scriptlet is used) #330.

v1.9.72 - 2023-08-25

Added

  • Conversion for scriptlets:
    • set-attr;
    • set-cookie;
    • set-local-storage-item;
    • set-session-storage-item.

v1.9.70 - 2023-08-21

Added

  • Support for XPath in xml-prune scriptlet #325.
  • Conversion of UBO's $redirect priority to the converter tsurlfilter#59.

Fixed

  • Issue with stack in json-prune scriptlet #348.
  • Issue with obligatoryProps in json-prune scriptlet #345.

v1.9.62 - 2023-08-04

Fixed

  • prevent-xhr closure bug on multiple requests #347.

v1.9.61 - 2023-08-01

Added

  • convertRedirectNameToAdg() method to convert redirect names to ADG #346.

v1.9.58 - 2023-07-27

Fixed

  • Escape commas in the params during conversion to ubo rules #343.

v1.9.57 - 2023-07-21

Added

  • Ability to remove an item from storage in set-local-storage-item and set-session-storage-item scriptlets #338.
  • New values to set-cookie and set-cookie-reload scriptlets: Accept, Reject, y, n, N, No, allow, deny #336.
  • Ability to use flags in regular expression scriptlet parameters #303.

Changed

  • Predefined values of set-cookie and set-cookie-reload are now case-insensitive #342.

Fixed

  • Overwriting google.ima value if it was already set #331.
  • Printing unnecessary logs to the console in log-addEventListener scriptlet #335.
  • Error throwing in prevent-fetch and prevent-xhr scriptlets when a request is blocked #334.

v1.9.37 - 2023-06-06

Added

  • evaldata-prune scriptlet #322.
  • trusted-replace-node-text scriptlet #319.
  • remove-node-text scriptlet #318.
  • Ability for prevent-element-src-loading scriptlet to prevent inline onerror and match link tag #276.
  • New special value modifiers for set-constant #316.

Changed

  • trusted-set-cookie and trusted-set-cookie-reload scriptlets to not encode cookie name and value #311.
  • Improved prevent-fetch: if responseType is not specified, original response type is returned instead of default #297.

Fixed

  • Pruning when addEventListener was used before calling send() method in m3u-prune and xml-prune scriptlets #315.
  • Issue with updateTargetingFromMap() method in googletagservices-gpt redirect #293.
  • Website reloading if $now$/$currentDate$ value is used in trusted-set-cookie-reload scriptlet #291.
  • getResponseHeader() and getAllResponseHeaders() methods mock in prevent-xhr scriptlet #295.

v1.9.7 - 2023-03-14

Added

  • Ability for trusted-click-element scriptlet to click element if cookie/localStorage item doesn't exist #298.
  • Static delay between multiple clicks in trusted-click-element #284.

Changed

  • Improved the convertScriptletToAdg() method — now it validates the input rule syntax if it is an ADG rule.

Fixed

  • Issue with MutationObserver.disconnect() in trusted-click-element #284.

v1.9.1 - 2023-03-07

Added

  • m3u-prune scriptlet #277.
  • true and false values for set-attr scriptlet #283.
  • UBO alias noop.css for noopcss redirect.

Changed

  • Decreased the minimal value for the boost parameter to 0.001 for adjust-setTimeout and adjust-setInterval #262.

Fixed

  • prevent-element-src-loading throwing error if thisArg is undefined #270.
  • Logging null in json-prune #282.
  • xml-prune: no pruning a request if new Request() is used, throwing an error while logging some requests #289.
  • Improve performance of the isValidScriptletName() method.

v1.8.2 - 2023-01-19

Added

  • trusted-set-constant scriptlet #137.
  • inject-css-in-shadow-dom scriptlet #267.
  • throwFunc and noopCallbackFunc prop values for set-constant scriptlet.
  • recreateIframeForSlot method mock to googletagservices-gpt redirect #259.

Changed

  • Added decimal delay matching for prevent-setInterval and prevent-setTimeout #247.
  • Debug logging to include rule text when available.
  • getScriptletFunction calls to throw error on unknown scriptlet names.

Fixed

  • prevent-xhr and trusted-replace-xhr-response closure bug on multiple requests #261.
  • Missing googletagmanager-gtm in compatibility table.

v1.7.20 - 2022-12-26

Added

  • isBlocking() method for Redirects class.
  • file field for redirect type.

Fixed

  • Redirects types.

v1.7.19 - 2022-12-22

Fixed

  • prevent-addEventListener and log-addEventListener loosing context. when encountering already bound .addEventListener.
  • google-ima3 conversion.

v1.7.14 - 2022-12-16

Added

v1.7.13 - 2022-12-13

Fixed

  • isEmptyObject helper not counting prototype as an object property.

v1.7.10 - 2022-12-07

Added

  • trusted-set-cookie-reload scriptlet.

Fixed

  • set-cookie-reload infinite page reloading #265.
  • Breakage of prevent-element-src-loading due to window getting into apply wrapper #264.
  • Spread of args bug at getXhrData call for trusted-replace-xhr-response.
  • Request properties array not being served to getRequestData and parseMatchProps helpers.

v1.7.3 - 2022-11-21

Added

  • Trusted scriptlets with extended capabilities:

    • trusted-click-element #23;
    • trusted-replace-xhr-response #202;
    • trusted-replace-fetch-response;
    • trusted-set-local-storage-item;
    • trusted-set-cookie.
  • Scriptlets:

Changed

  • Scriptlets:
    • prevent-element-src-loading #228;
    • prevent-fetch #216;
    • abort-on-stack-trace #201;
    • abort-current-inline-script #251;
    • set-cookie & set-cookie-reload.
  • Redirects:
    • google-ima3 #255;
    • metrika-yandex-tag #254;
    • googlesyndication-adsbygoogle #252.