防止特定内联脚本标签的执行

9
我正在尝试编写一个Tampermonkey脚本,以防止特定的内联脚本标签执行。页面主体看起来像这样。
<body>
  <!-- the following script tag should be executed-->
  <script type="text/javascript">
    alert("I'm executed as normal")
  </script>
  <!-- the following script tag should NOT be executed-->
  <script type="text/javascript">
    alert("I should not be executed")
  </script>
  <!-- the following script tag should be executed-->
  <script type="text/javascript">
    alert("I'm executed as normal, too")
  </script>
</body>

我试图使用Tampermonkey脚本删除script标签,但是如果我在document-startdocument-body运行它,则script标签尚不存在。如果我在document-enddocument-idle运行它,则我想要删除的script标签将在我的Tampermonkey脚本执行之前运行。
我该如何防止执行script标签?
注意:我想要防止执行的实际script标签包含window.location = 'redirect-url'。因此,在这种情况下,防止重新加载也足够了。

版本信息:

  • Chromium 65.0.3325.181
  • Tampermonkey 4.5

2
在Chrome中没有办法阻止它,但是你可以停止加载、获取和重写页面的HTML(示例)。 - wOxxOm
谢谢,这帮助我找到了一个类似的解决方案 - maiermic
另一个可能的解决方案是在 document_start 时将变异观察器附加到 document.documentElement 上,并在添加脚本后将其删除。这在 Chrome 85 中对我有效。 - teg_brightly
2个回答

6

删除脚本标签在 document-start (建议来自 wOxxOm):

(function() {
    'use strict';
    window.stop();
    const xhr = new XMLHttpRequest();
    xhr.open('GET', window.location.href);
    xhr.onload = () => {
        var html = xhr.responseText
        .replace(/<script\b[\s\S]*?<\/script>/g, s => {
            // check if script tag should be replaced/deleted
            if (s.includes('window.location')) {
                return '';
            } else {
                return s;
            }
        });
        document.open();
        document.write(html);
        document.close();
    };
    xhr.send();
})();

我使用了你的代码,它完美地运行了,除了在我的Vivaldi浏览器中没有显示网站图标。你有什么想法是这种行为的原因吗?我在https://stackoverflow.com/questions/65103986/favicon-disappears-after-preventing-execution-of-a-specific-inline-script-tag-by上提出了一个问题。 - azerbajdzan
@azerbajdzan 我看到你已经找到了一个关于你问题的答案 - maiermic

1

不使用doc.write/XHR的替代版本 --

   (() => { 
          'use strict';
          let needle = '/window.location/';
          if ( needle === '' || needle === '{{1}}' ) {
              needle = '.?';
          } else if ( needle.slice(0,1) === '/' && needle.slice(-1) === '/' ) {
              needle = needle.slice(1,-1);
          } else {
              needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
          }
          needle = new RegExp(needle);
          const jsnode = () => {
                        try {
                            const jss = document.querySelectorAll('script');
                            for (const js of jss) {
                                if (js.outerHTML.match(needle)) {
                                        js.remove();
                                }           
                            }
                        } catch { }
          };
          const observer = new MutationObserver(jsnode);
          observer.observe(document.documentElement, { childList: true, subtree: true });
})();

使用MutationObserver的修改版本,尝试一下并让我知道它是否适用于您。 - user11590849
请提供无法正常工作的网址,以便我自己复制。这种情况是在Firefox还是Chrome上发生的? - user11590849
1
当然,如果一开始就不起作用,我也不会发布。例如,sportingnews.com,他们通过Instart Logic插入广告,因此将/window.location/替换为/INSTART/并浏览该网站,没有Instart g00垃圾将被加载,即使您通过devtools检查,它们的域名也不会发出网络请求。您在本地主机上进行了测试,我无法这样做,因为我只在路由器上运行而已。我建议您在建议的网站上进行测试。还要确保在文档开始处插入代码片段。 - user11590849
1
由于原始网站已不存在,我创建了一个网站 https://prevent-execution-of-a-specific-inline-script-tag.surge.sh 来为您进行测试,并将其重定向到此问题。请尝试防止重定向。 - maiermic
1
竞态条件。在那里,没有任何JS片段可以工作,包括woXXom发布的那个。对于那个,您需要CSP来中止执行。 - user11590849
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接