AdguardTeam / Scriptlets

AdGuard scriptlets library
GNU General Public License v3.0
138 stars 27 forks source link

Improve 'prevent-fetch' — add 'cors' responseType #394

Closed Yuki2718 closed 3 months ago

Yuki2718 commented 6 months ago

prevent-fetch has to set responseType cors to fix https://github.com/AdguardTeam/AdguardFilters/issues/153796. I confirmed it works on uBO 1.54.1 rc2 https://github.com/gorhill/uBlock/commit/e1ae17ed0059f5be488f2d6b7617feeda63e9096 However, on AG extension 4.2.241 rekidai-info.github.io#%#//scriptlet('prevent-fetch', 'pagead2.googlesyndication.com') doesn't even prevent the fetch request on my end.

Yuki2718 commented 3 months ago

Here https://h5games.success-corp.co.jp/game/play/su-300-mss success-corp.co.jp#%#//scriptlet('prevent-fetch', 'pagead2.googlesyndication.com') doesn't work on extension 4.3.35. It works on uBO though.

slavaleleka commented 3 months ago

it is not included into the extension 4.3.35

Yuki2718 commented 3 months ago

I'm not sure if this is the same issue. The rule doesn't prevent fetch request and let anti-adb to appear after you click GAME START. Same on beta too.

Screenshot ![anti-adb](https://github.com/AdguardTeam/Scriptlets/assets/58900598/ad366980-737f-421c-b4d5-34b0647d03de)
AdamWr commented 3 months ago

This is a scriptlet with latest changes converted to JavaScript rule:

rekidai-info.github.io,success-corp.co.jp#%#!function(e,t){function r(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"emptyObj",i=arguments.length>3?arguments[3]:void 0;if("undefined"!=typeof fetch&&"undefined"!=typeof Proxy&&"undefined"!=typeof Response){var u,s=Request.prototype.clone;if(""===r||"emptyObj"===r)u="{}";else if("emptyArr"===r)u="[]";else{if("emptyStr"!==r)return void c(e,"Invalid responseBody parameter: '".concat(r,"'"));u=""}if(!(void 0!==i)||function(e){return["basic","cors","opaque"].includes(e)}(i)){var l={apply:async function(r,l,f){var d,v=function(e,t){var r,n,o={},c=e[0];if(c instanceof Request){var a=t.call(c),i=(u=a,s=["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"].map((function(e){return[e,u[e]]})),Object.fromEntries(s));r=i.url,n=i}else r=c,n=e[1];var u,s;if(o.url=r,n instanceof Object){Object.keys(n).forEach((function(e){o[e]=n[e]}))}return o}(f,s);if(void 0===t)return c(e,"fetch( ".concat(o(v)," )"),!0),n(e),Reflect.apply(r,l,f);if(d=function(e,t,r){if(""===t||"*"===t)return!0;var n,o=(a=t,i=" ",u=":",s=function(e){return["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"].includes(e)},l={},a.split(i).forEach((function(e){var t=e.indexOf(u),r=e.slice(0,t);if(s(r)){var n=e.slice(t+1);l[r]=n}else l.url=e})),l);var a,i,u,s,l;if(d=o,Object.values(d).every((function(e){return function(e){var t,r="/",n=function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(e);e[0]===r&&e[e.length-1]===r&&(n=e.slice(1,-1));try{t=new RegExp(n),t=!0}catch(e){t=!1}return t}(e)}))){var f=function(e){var t={},r=Object.keys(e);return r.forEach((function(r){t[r]=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=".?",r="/";if(""===e)return new RegExp(t);var n=e.lastIndexOf(r),o=e.substring(n+1),c=e.substring(0,n+1),a=function(e){if(!e)return!1;try{return new RegExp("",e),!0}catch(e){return!1}},i=(u=c,s=o,u.startsWith(r)&&u.endsWith(r)&&!u.endsWith("\\/")&&a(s)?s:"");var u,s;if(e.startsWith(r)&&e.endsWith(r)||i){return new RegExp((i?c:e).slice(1,-1),i)}var l=e.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(l)}(e[r])})),t}(o);n=Object.keys(f).every((function(e){var t=f[e],n=r[e];return Object.prototype.hasOwnProperty.call(r,e)&&"string"==typeof n&&(null==t?void 0:t.test(n))}))}else c(e,"Invalid parameter: ".concat(t)),n=!1;var d;return n}(e,t,v),d){var p;n(e);try{p=i||function(t){try{var r=t.mode;if(void 0===r||"cors"===r||"no-cors"===r)return new URL(t.url).origin===document.location.origin?"basic":"no-cors"===r?"opaque":"cors"}catch(t){c(e,"Could not determine response type: ".concat(t))}}(v);var y=await Reflect.apply(r,l,f);return y.ok?function(e){var t,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{body:"{}"},n={};null==e||null===(t=e.headers)||void 0===t||t.forEach((function(e,t){n[t]=e}));var o=new Response(r.body,{status:e.status,statusText:e.statusText,headers:n});return Object.defineProperties(o,{url:{value:e.url},type:{value:r.type||e.type}}),o}(y,{body:u,type:p}):a(u,v.url,p)}catch(e){return a(u,v.url,p)}}return Reflect.apply(r,l,f)}};fetch=new Proxy(fetch,l)}else c(e,"Invalid responseType parameter: '".concat(i,"'"))}}function n(e){if(!0===e.verbose){try{var t=console.log.bind(console),r=console.trace.bind(console),n=e.ruleText||"";if(e.domainName){var o,c="#%#//",a="##+js";e.ruleText.includes(c)?o=e.ruleText.indexOf(c):e.ruleText.includes(a)&&(o=e.ruleText.indexOf(a));var i=e.ruleText.slice(o);n="".concat(e.domainName).concat(i)}t("".concat(n," trace start")),r&&r(),t("".concat(n," trace end"))}catch(e){}"function"==typeof window.__debug&&window.__debug(e)}}function o(e){return e&&"object"==typeof e?function(e){return 0===Object.keys(e).length&&!e.prototype}(e)?"{}":Object.entries(e).map((function(e){var t=e[0],r=e[1],n=r;return r instanceof Object&&(n="{ ".concat(o(r)," }")),"".concat(t,':"').concat(n,'"')})).join(" "):String(e)}function c(e,t){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=e.name,c=e.verbose;if(r||c){var a=console.log;n?a("".concat(o,": ").concat(t)):a("".concat(o,":"),t)}}function a(){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"basic";if("undefined"!=typeof Response){var r=new Response(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"{}",{status:200,statusText:"OK"});return"opaque"===t?Object.defineProperties(r,{body:{value:null},status:{value:0},statusText:{value:""},url:{value:""},type:{value:t}}):Object.defineProperties(r,{url:{value:e},type:{value:t}}),Promise.resolve(r)}}var i=t?[].concat(e).concat(t):[e];try{r.apply(this,i)}catch(e){console.log(e)}}({name:"prevent-fetch",args:["adsbygoogle","emptyStr"],verbose:!0},["adsbygoogle","emptyStr"]);

and it seems that it works fine on my end.

Please note that in network panel, a network request still will be visible as blocked if it's blocked by extension/app (or unblocked if there is no blocking rule), that's how it works in current implementation and it's not an issue.


Regarding rekidai-info.github.io, in addition to prevent-fetch (or script above) this rule is also needed:

rekidai-info.github.io#%#window.adsbygoogle = { loaded: true, push: (a)=>{if(!a) { throw new Error('called with no parameters'); }} };
Yuki2718 commented 3 months ago

Confirmed the JS rule works. Yeah, rekidai-info.github.io script is updated.

Yuki2718 commented 6 days ago

Current code of rekidai-info.github.io

async function ti() {
    try {
        const y = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?_=" + Date.now()
          , t = await fetch(y, {
            cache: "no-store",
            redirect: "error"
        });
        if (t.type !== "cors" || t.url !== y || t.body == null || t.redirected || t.status !== 200)
            throw Error("Ad blocker detected.")
    } catch {
        throw Error("Ad blocker detected.")
    }
    try {
        const y = "https://pagead2.googlesyndication.com/a.js?_=" + Date.now()
          , t = await fetch(y, {
            cache: "no-store"
        });
        if (t.type !== "cors" || t.url !== y || t.body == null || t.redirected || t.status !== 200)
            throw Error("Ad blocker detected.")
    } catch (y) {
        if (y.toString().indexOf("Ad blocker detected.") >= 0)
            throw y
    }
    if (window.adsbygoogle == null || window.adsbygoogle.push == null || typeof window.adsbygoogle.push != "function")
        throw Error("Ad blocker detected.");
    (function() {
        let y = !1;
        if (["p", "q"].forEach(t=>{
            Array(26).fill(1).map((r,n)=>String.fromCharCode(65 + n) + t).concat(Array(26).fill(1).map((r,n)=>String.fromCharCode(97 + n) + t)).forEach(r=>{
                if (window[r] != null || window.adsbygoogle[r] != null)
                    throw Error("Ad blocker detected.");
                if (!y) {
                    let n = window.adsbygoogle.push.toString();
                    RegExp(`^[a-z]=>\\{${r}\\([a-z],[a-z],[a-z]\\)\\}$`, "g").test(n) && (y = !0)
                }
            }
            )
        }
        ),
        !y)
            throw Error("Ad blocker detected.")
    }
    )();
    try {
        window.adsbygoogle.push()
    } catch {
        try {
            window.adsbygoogle.push(!0)
        } catch {
            const r = await fetch("rekidai.min.json", {
                method: "GET",
                mode: "same-origin",
                cache: "no-cache",
                credentials: "same-origin"
            })
              , n = await r.json();
            if (r.ok)
                return n.filter(f=>f.music !== "罪過の聖堂");
            throw Error("Error Loading Rekidai Data.")
        }
    }
    throw Error("Ad blocker detected.")
}

for uBO fixed with rekidai-info.github.io##+js(prevent-fetch, /a(dsbygoogle)?\.js/, war:googlesyndication_adsbygoogle.js, '{ "type": "cors" }') which I don't think AG has the counterpart. war was added by https://github.com/gorhill/uBlock/commit/6aeab2adbc95e1e892867ad719b02cf1d1dc9a61

AdamWr commented 6 days ago

I think that the problem is that website overrides Object.defineProperties which is used by prevent-fetch. These rules:

@@||pagead2.googlesyndication.com^$xmlhttprequest,domain=rekidai-info.github.io,badfilter
@@||pagead2.googlesyndication.com/pagead/js/adsbygoogle.js$domain=rekidai-info.github.io,badfilter
rekidai-info.github.io#%#//scriptlet('prevent-fetch', 'googlesyndication')
rekidai-info.github.io#%#(()=>{const k={};const f=[];const qq=function(m,k,f){if(!m||m===!0)throw new Error("called with no parameters");};window.adsbygoogle={loaded:true,push:m=>{qq(m,k,f)}}})();
rekidai-info.github.io#%#!function(){const e={set:(e,t,n,o)=>!(!t||"defineProperties"!==t)||Reflect.set(e,t,n,o)};window.Object=new Proxy(window.Object,e)}();

seem to work fine.

Yuki2718 commented 6 days ago

Confirmed, working!