Stop Nefarious Redirects

Block unauthorized redirects and prevent history manipulation

当前为 2024-05-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Stop Nefarious Redirects
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.89
  5. // @description Block unauthorized redirects and prevent history manipulation
  6. // @match http://*/*
  7. // @match https://*/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @grant GM_xmlhttpRequest
  11. // @license MIT
  12. // @run-at document-start
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // Manual blacklist
  19. const manualBlacklist = new Set([
  20. 'getrunkhomuto.info'
  21. ]);
  22.  
  23. // Function to get the current automated blacklist
  24. function getAutomatedBlacklist() {
  25. return new Set(GM_getValue('blacklist', []));
  26. }
  27.  
  28. // Function to add a URL to the automated blacklist
  29. function addToAutomatedBlacklist(url) {
  30. let encodedUrl = encodeURIComponent(url);
  31. let blacklist = getAutomatedBlacklist();
  32. if (!blacklist.has(encodedUrl)) {
  33. blacklist.add(encodedUrl);
  34. GM_setValue('blacklist', Array.from(blacklist));
  35. console.log('Added to automated blacklist:', url);
  36. }
  37. }
  38.  
  39. // Function to display the blacklist
  40. function displayBlacklist() {
  41. let automatedBlacklist = getAutomatedBlacklist();
  42. let fullBlacklist = new Set([...manualBlacklist, ...automatedBlacklist]);
  43. console.log('Current Blacklist:\n' + Array.from(fullBlacklist).map(decodeURIComponent).join('\n'));
  44. alert('Current Blacklist:\n' + Array.from(fullBlacklist).map(decodeURIComponent).join('\n'));
  45. }
  46.  
  47. // Function to handle navigation events
  48. function handleNavigation(url) {
  49. try {
  50. if (!isUrlAllowed(url)) {
  51. console.error('Blocked navigation to:', url);
  52. addToAutomatedBlacklist(url); // Add the unauthorized URL to the automated blacklist
  53. if (lastKnownGoodUrl) {
  54. window.location.replace(lastKnownGoodUrl);
  55. }
  56. return false;
  57. } else {
  58. console.log('Navigation allowed to:', url);
  59. lastKnownGoodUrl = url;
  60. return true;
  61. }
  62. } catch (error) {
  63. console.error('Error in handleNavigation:', error);
  64. }
  65. }
  66.  
  67. let lastKnownGoodUrl = window.location.href;
  68. let navigationInProgress = false;
  69.  
  70. // Proxy to intercept and handle location changes
  71. const locationProxy = new Proxy(window.location, {
  72. set(target, prop, value) {
  73. if ((prop === 'href' || prop === 'assign' || prop === 'replace') && !navigationInProgress) {
  74. if (!handleNavigation(value)) {
  75. return false;
  76. }
  77. }
  78. return Reflect.set(target, prop, value);
  79. },
  80. get(target, prop) {
  81. if (prop === 'assign' || prop === 'replace') {
  82. return function(url) {
  83. if (!navigationInProgress && handleNavigation(url)) {
  84. navigationInProgress = true;
  85. setTimeout(() => {
  86. navigationInProgress = false;
  87. }, 0);
  88. return target[prop].call(target, url);
  89. }
  90. };
  91. }
  92. return Reflect.get(target, prop);
  93. }
  94. });
  95.  
  96. // Replace window.location with the proxy
  97. Object.defineProperty(window, 'location', {
  98. configurable: true,
  99. enumerable: true,
  100. get() {
  101. return locationProxy;
  102. }
  103. });
  104.  
  105. // Monitor window.open() calls
  106. const originalOpen = window.open;
  107. window.open = function(url) {
  108. if (handleNavigation(url)) {
  109. return originalOpen.apply(this, arguments);
  110. }
  111. };
  112.  
  113. // Monitor document.createElement('a') calls
  114. const originalCreateElement = document.createElement;
  115. document.createElement = function(tagName) {
  116. const element = originalCreateElement.call(document, tagName);
  117. if (tagName.toLowerCase() === 'a') {
  118. const originalSetAttribute = element.setAttribute;
  119. element.setAttribute = function(name, value) {
  120. if (name === 'href') {
  121. if (!handleNavigation(value)) {
  122. return;
  123. }
  124. }
  125. return originalSetAttribute.apply(this, arguments);
  126. };
  127. }
  128. return element;
  129. };
  130.  
  131. // Enhanced navigation control for back/forward buttons
  132. window.addEventListener('popstate', function(event) {
  133. if (!navigationInProgress && !isUrlAllowed(window.location.href)) {
  134. console.error('Blocked navigation to:', window.location.href);
  135. navigationInProgress = true;
  136. setTimeout(() => {
  137. navigationInProgress = false;
  138. }, 0);
  139. history.pushState(null, "", lastKnownGoodUrl); // Push the last known good URL
  140. window.location.replace(lastKnownGoodUrl); // Force redirect to last known good URL
  141. event.preventDefault();
  142. }
  143. });
  144.  
  145. // Function to handle history manipulation
  146. function handleHistoryManipulation(originalMethod, data, title, url) {
  147. if (!isUrlAllowed(url)) {
  148. console.error('Blocked history manipulation to:', url);
  149. return;
  150. }
  151. return originalMethod.call(history, data, title, url);
  152. }
  153.  
  154. // Wrap history.pushState and history.replaceState
  155. const originalPushState = history.pushState;
  156. const originalReplaceState = history.replaceState;
  157.  
  158. history.pushState = function(data, title, url) {
  159. return handleHistoryManipulation(originalPushState, data, title, url);
  160. };
  161.  
  162. history.replaceState = function(data, title, url) {
  163. return handleHistoryManipulation(originalReplaceState, data, title, url);
  164. };
  165.  
  166. // Ensure we have a state to go back to if needed
  167. if (history.length === 1) {
  168. // Directly landed on this page, fake history
  169. history.replaceState(null, "", "/");
  170. history.pushState(null, "", window.location.href);
  171. }
  172.  
  173. // Function to check if a URL is allowed based on the blacklist
  174. function isUrlAllowed(url) {
  175. let encodedUrl = encodeURIComponent(url);
  176. let automatedBlacklist = getAutomatedBlacklist();
  177. let isBlocked = Array.from(manualBlacklist).some(blockedUrl => encodedUrl.includes(blockedUrl)) ||
  178. Array.from(automatedBlacklist).some(blockedUrl => encodedUrl.includes(blockedUrl));
  179. if (isBlocked) {
  180. console.log(`Blocked URL: ${url}`);
  181. }
  182. return !isBlocked;
  183. }
  184.  
  185. console.log('Redirect control script with blacklist initialized.');
  186. })();