From e1a54ba2761a5be718ffee015d2a95c0d1b70af3 Mon Sep 17 00:00:00 2001 From: Ghostery Adblocker Bot Date: Fri, 30 Oct 2026 20:10:38 +0000 Subject: [PATCH] Update scriptlets --- package.json | 2 +- ubo.js | 84 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 79f3bd1..9b49fad 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "type": "module", "scripts": { - "build": "deno build.ts --tagName 1.75.1b1 > ubo.js", + "build": "deno build.ts --tagName 1.75.1rc4 > ubo.js", "test": "node --test" }, "author": { diff --git a/ubo.js b/ubo.js index fd9ad99..c891056 100644 --- a/ubo.js +++ b/ubo.js @@ -238,6 +238,14 @@ fn: 'trustedJsonEditFetchResponse', }; +scriptlets['trusted-edit-inbound-element.js'] = { +aliases: [], + +requiresTrust: true, +fn: 'trustedEditInboundElement', +}; + + scriptlets['json-edit-fetch-request.js'] = { aliases: [], @@ -2497,7 +2505,12 @@ class JSONPath { if ( rval instanceof Object === false ) { return; } const lval = obj[key]; if ( lval instanceof Object === false ) { return; } - if ( Array.isArray(lval) ) { return; } + if ( Array.isArray(lval) ) { + if ( Array.isArray(rval) ) { + lval.push(...rval); break; + } + lval.push(rval); break; + } for ( const [ k, v ] of JSONPath.entries(rval) ) { lval[k] = v; } @@ -3192,6 +3205,55 @@ function jsonEditFetchRequestFn(trusted, jsonq = '', ...varargs) { proxyApplyFn('fetch', proxyHandler); proxyApplyFn('Request', proxyHandler); } +async function editInboundElementFn( + trusted = false, + propChain = '', + argPosRaw = '', + selector = '', + jsonq = '' +) { + if ( propChain === '' ) { return; } + if ( selector === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-inbound-element`, + propChain, argPosRaw, selector, jsonq + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const argPos = parseInt(argPosRaw, 10); + const getElem = context => { + if ( argPosRaw === 'this' ) { return context.thisArg; } + const { callArgs } = context; + if ( Array.isArray(callArgs) === false ) { return; } + if ( isNaN(argPos) ) { return; } + if ( argPos >= 0 ) { + if ( callArgs.length <= argPos ) { return; } + return callArgs[argPos]; + } + if ( callArgs.length < -argPos ) { return; } + return callArgs[callArgs.length + argPos]; + }; + const editElem = elem => { + if ( elem instanceof Element === false ) { return; } + if ( elem.matches(selector) === false ) { return; } + elem = jsonp.apply(elem); + if ( elem === undefined ) { return; } + safe.uboLog(logPrefix, 'Edited'); + }; + proxyApplyFn(propChain, function(context) { + const elem = getElem(context); + if ( elem !== undefined ) { + editElem(elem); + } + return context.reflect(); + }); +} +function trustedEditInboundElement(...args) { + editInboundElementFn(true, ...args); +} function jsonEditFetchRequest(jsonq = '', ...args) { jsonEditFetchRequestFn(false, jsonq, ...args); } @@ -6887,16 +6949,18 @@ function trustedPreventDomBypass( } } if ( targetProp !== '' ) { + const chains = targetProp.split(/\s+/); let me = self, it = elem.contentWindow; - let chain = targetProp; - for (;;) { - const pos = chain.indexOf('.'); - if ( pos === -1 ) { break; } - const prop = chain.slice(0, pos); - me = me[prop]; it = it[prop]; - chain = chain.slice(pos+1); + for ( let chain of chains ) { + for (;;) { + const pos = chain.indexOf('.'); + if ( pos === -1 ) { break; } + const prop = chain.slice(0, pos); + me = me[prop]; it = it[prop]; + chain = chain.slice(pos+1); + } + it[chain] = me[chain]; } - it[chain] = me[chain]; } else { Object.defineProperty(elem, 'contentWindow', { value: self }); } @@ -6940,7 +7004,7 @@ function trustedOverrideElementMethod( return validateConstantFn(true, disposition, extraArgs); }); } -const table = { abortCurrentScript, setAttr, trustedSetAttr, removeAttr, trustedCreateHTML, hrefSanitizer, proxyApplyConfig, editOutboundObject, trustedEditOutboundObject, jsonEdit, trustedJsonEdit, editInboundObject, trustedEditInboundObject, editThisObject, trustedEditThisObject, editObjectOnGetter, trustedEditObjectOnGetter, editObjectOnSetter, trustedEditObjectOnSetter, editElementObject, trustedEditElementObject, jsonEditXhrResponse, trustedJsonEditXhrResponse, jsonEditXhrRequest, trustedJsonEditXhrRequest, jsonEditFetchResponse, trustedJsonEditFetchResponse, jsonEditFetchRequest, trustedJsonEditFetchRequest, jsonlEditXhrResponse, trustedJsonlEditXhrResponse, jsonlEditFetchResponse, trustedJsonlEditFetchResponse, abortOnStackTrace, trustedPruneInboundObject, trustedPruneOutboundObject, jsonPrune, jsonPruneFetchResponse, jsonPruneXhrResponse, evaldataPrune, noEvalIf, preventAddEventListener, preventBab, preventClipboardWrite, preventDialog, preventFetch, trustedPreventFetch, freezeElementProperty, preventInnerHTML, preventNavigation, preventSetTimeout, preventSetInterval, preventRequestAnimationFrame, setConstant, trustedSetConstant, trustedReplaceArgument, spoofCSS, preventXhr, trustedPreventXhr, mpegdashPrune, setCookie, setCookieReload, trustedSetCookie, trustedSetCookieReload, removeCookie, setLocalStorageItem, setSessionStorageItem, trustedSetLocalStorageItem, trustedSetSessionStorageItem, abortOnPropertyRead, abortOnPropertyWrite, adjustSetInterval, adjustSetTimeout, preventRefresh, removeClass, webrtcIf, noWindowOpenIf, closeWindow, windowNameDefuser, overlayBuster, alertBuster, noWebrtc, disableNewtabLinks, xmlPrune, m3uPrune, callNothrow, removeNodeText, preventCanvas, multiup, breakOnCall, replaceNodeText, trustedReplaceFetchResponse, trustedReplaceXhrResponse, trustedClickElement, trustedReplaceOutboundText, trustedSuppressNativeMethod, trustedPreventDomBypass, trustedOverrideElementMethod }; +const table = { abortCurrentScript, setAttr, trustedSetAttr, removeAttr, trustedCreateHTML, hrefSanitizer, proxyApplyConfig, editOutboundObject, trustedEditOutboundObject, jsonEdit, trustedJsonEdit, editInboundObject, trustedEditInboundObject, editThisObject, trustedEditThisObject, editObjectOnGetter, trustedEditObjectOnGetter, editObjectOnSetter, trustedEditObjectOnSetter, editElementObject, trustedEditElementObject, jsonEditXhrResponse, trustedJsonEditXhrResponse, jsonEditXhrRequest, trustedJsonEditXhrRequest, jsonEditFetchResponse, trustedJsonEditFetchResponse, trustedEditInboundElement, jsonEditFetchRequest, trustedJsonEditFetchRequest, jsonlEditXhrResponse, trustedJsonlEditXhrResponse, jsonlEditFetchResponse, trustedJsonlEditFetchResponse, abortOnStackTrace, trustedPruneInboundObject, trustedPruneOutboundObject, jsonPrune, jsonPruneFetchResponse, jsonPruneXhrResponse, evaldataPrune, noEvalIf, preventAddEventListener, preventBab, preventClipboardWrite, preventDialog, preventFetch, trustedPreventFetch, freezeElementProperty, preventInnerHTML, preventNavigation, preventSetTimeout, preventSetInterval, preventRequestAnimationFrame, setConstant, trustedSetConstant, trustedReplaceArgument, spoofCSS, preventXhr, trustedPreventXhr, mpegdashPrune, setCookie, setCookieReload, trustedSetCookie, trustedSetCookieReload, removeCookie, setLocalStorageItem, setSessionStorageItem, trustedSetLocalStorageItem, trustedSetSessionStorageItem, abortOnPropertyRead, abortOnPropertyWrite, adjustSetInterval, adjustSetTimeout, preventRefresh, removeClass, webrtcIf, noWindowOpenIf, closeWindow, windowNameDefuser, overlayBuster, alertBuster, noWebrtc, disableNewtabLinks, xmlPrune, m3uPrune, callNothrow, removeNodeText, preventCanvas, multiup, breakOnCall, replaceNodeText, trustedReplaceFetchResponse, trustedReplaceXhrResponse, trustedClickElement, trustedReplaceOutboundText, trustedSuppressNativeMethod, trustedPreventDomBypass, trustedOverrideElementMethod }; for (const [name, ...args] of calls) { try { table[name](...args); } catch {} }