Scriptlets icon indicating copy to clipboard operation
Scriptlets copied to clipboard

Improve `prevent-element-src-loading` — inline `onerror` support?

Open contribucious opened this issue 3 years ago • 2 comments

Hi,

This aims to improve the prevent-element-src-loading scriptlet (see this comment — and the issue) and is based on a concrete example. (Example which in this case can be resolved differently but that's not what interests us here.)

Concerned code

Click to reveal …  

view-source:https://www.leconomiste.com/

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" onerror="showPopup();"></script>

<script>
function showPopup() {
  document.getElementById('boxes').style.display='block';
}
</script>

<div id='boxes' style='display:none;'>
  <div style='top: 199.5px; left: 450px; display: none;z-index: 99999; background:#fff;height:350px' id='dialog' class='window'>
    <div style="text-align:center;">
      <img src='sites/all/themes/eco7_vf/images/adblock1.jpg' />
      <h1>Vous utilisez un bloqueur de publicité</h1>
      <p>Merci de désactiver le bloqueur de publicité avant de naviguer sur notre site.</p>
    </div>
  </div>
  <div style='width: 1478px; height: 1002px; display: none; opacity: 0.8;top: -72px;' id='mask'></div>
</div>

 

Steps to reproduce

Click to reveal …

Steps

  1. Add this DNS user rule (in the way you like): ||pagead2.googlesyndication.com^

  2. Only if you use AdGuard for Windows/Mac/Android, add this user rule first (just to avoid deletion of the concerned script tag in the HTML code due to existing rules): @@||pagead2.googlesyndication.com/pagead/js/adsbygoogle.js$domain=leconomiste.com

  3. Add this user rule: leconomiste.com#%#//scriptlet('prevent-element-src-loading', 'script', 'adsbygoogle')

Expected behavior

Inline onerror code used by the website: onerror="showPopup();"

is not executed. In the same way as if this had been used instead:

[…]

script.onerror = () => {
  showPopup();
};

script.src = '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';

[…]

Actual behavior

Inline onerror code is executed.  

Additional information

Click to reveal …  

Remark:

  • Make sure it's OK too if this is done later by the website:
[…]
script.setAttribute('onerror', '[…]');
script.setAttribute('src', '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js');
[…]

Related link:

  • https://www.webtips.dev/how-to-reliably-check-if-adblocker-is-enabled (search adsbygoogle on the page)
 

contribucious avatar Jul 15 '22 15:07 contribucious

If I'm not wrong, something like this:

Code
function preventError(src) {
  window.addEventListener('error', function (event) {
    /* or event.target */
    if (!event.srcElement || !event.srcElement.src) {
      return;
    }

    const regex = new RegExp(src);

    if (!regex.test(event.srcElement.src)) {
      return;
    }

    if (typeof event.srcElement.onload === 'function') {
      return event.srcElement.onerror = event.srcElement.onload;
    }

    return event.srcElement.onerror = function () {};
  }, true);
};
preventError("adsbygoogle");

Rule:

leconomiste.com#%#function preventError(a){window.addEventListener("error",function(b){if(b.srcElement&&b.srcElement.src){const c=new RegExp(a);return c.test(b.srcElement.src)?"function"==typeof b.srcElement.onload?b.srcElement.onerror=b.srcElement.onload:b.srcElement.onerror=function(){}:void 0}},!0)};preventError("adsbygoogle");

should fixes it and other similar cases with onerror attribute.

I guess that it may requires more improvements/tweaks, but perhaps it will be helpful to improve a current scriptlet or create a new one, maybe there is a better way to fix it, just an idea.

AdamWr avatar Jul 16 '22 15:07 AdamWr

:heavy_check_mark: Nice work. The above rule allows, indeed, to fix this case on my side too. (Tested both on AdGuard for Windows 7.10.1 and on AdGuard Browser extension 4.0.181.)

Let's wait and see what @slavaleleka and/or @stanislav-atr think of this solution! :wink:

contribucious avatar Jul 16 '22 16:07 contribucious