Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to block javascript using javascript?

I'm trying to make an extension for Safari that lets users block javascript per-site, using the new API. The API lets you inject a javascript file that will be loaded onto websites before any of the content, with not much functionality than regular javascript as if it was running on an HTML page. Is there a way to block all javascript using javascript?

The API tells me, vaguely, that "The injected scripts are executed before the webpage has been fully loaded, so you can take action as resources are added to the webpage." Is there some event I can hook into to catch resources being loaded, and block them?

like image 952
user5074736 Avatar asked May 14 '26 13:05

user5074736


1 Answers

There's a way to block most Javascript: attach a MutationObserver at the very beginning of pageload, and whenever the document changes, if a <script> tag is found, remove it:

<script>
new MutationObserver(() => {
  console.log('Mutation observer running...');
  document.body.querySelectorAll('script').forEach(scr => scr.remove());
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>

Javascript from inline handlers can still run, but luckily, inline Javascript isn't so common in comparison to <script> tags (since it's bad practice), and, usually, all the substantive Javascript will be in a <script> tag regardless, so inline Javascript will probably often simply throw an error due to referencing an undefined function.

Although subtree: true is significantly more expensive than other MutationObservers when elements are added dynamically, since there's (almost certainly) no Javascript running on the page, it shouldn't be an issue, especially once the page has fully loaded.

To remove inline handlers as well, check if the added element has on attributes, and remove them:

<script>
const cleanNode = (node) => {
  if (node.nodeType !== 1) {
    // Not an element node:
    return;
  }
  if (node.matches('script')) {
    node.remove();
  }
  [...node.attributes].forEach((attr) => {
    if (attr.name.startsWith('on')) {
      node.removeAttribute(attr.name);
    }
  });
};
new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    [...mutation.addedNodes].forEach(cleanNode);
  });
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>
<img onerror="alert('JS running')" src>
like image 65
CertainPerformance Avatar answered May 17 '26 01:05

CertainPerformance



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!