Stop Nefarious Redirects

Block unauthorized redirects and prevent history manipulation

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

  1. // ==UserScript==
  2. // @name Stop Nefarious Redirects
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.83
  5. // @description Block unauthorized redirects and prevent history manipulation
  6. // @match http://*/*
  7. // @match https://*/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @license MIT
  11. // @run-at document-start
  12. // ==/UserScript==
  13. (function() {
  14. 'use strict';
  15. // Function to get the current blacklist
  16. function getBlacklist() {
  17. return new Set(GM_getValue('blacklist', []));
  18. }
  19. // Function to add a URL to the blacklist
  20. function addToBlacklist(url) {
  21. let blacklist = getBlacklist();
  22. if (!blacklist.has(url)) {
  23. blacklist.add(url);
  24. GM_setValue('blacklist', Array.from(blacklist));
  25. }
  26. }
  27. // Function to display the blacklist
  28. function displayBlacklist() {
  29. let blacklist = getBlacklist();
  30. console.log('Current Blacklist:\n' + Array.from(blacklist).join('\n'));
  31. }
  32. // Debounce function
  33. function debounce(func, delay) {
  34. let timeoutId;
  35. return function(...args) {
  36. clearTimeout(timeoutId);
  37. timeoutId = setTimeout(() => func.apply(this, args), delay);
  38. };
  39. }
  40. // Function to handle navigation events
  41. const handleNavigation = debounce(function(url) {
  42. try {
  43. if (!isUrlAllowed(url)) {
  44. console.error('Blocked navigation to:', url);
  45. addToBlacklist(url); // Add the unauthorized URL to the blacklist
  46. if (lastKnownGoodUrl) {
  47. window.location.replace(lastKnownGoodUrl);
  48. }
  49. return false;
  50. } else {
  51. console.log('Navigation allowed to:', url);
  52. lastKnownGoodUrl = url;
  53. return true;
  54. }
  55. } catch (error) {
  56. console.error('Error in handleNavigation:', error);
  57. }
  58. }, 100);
  59. let lastKnownGoodUrl = window.location.href;
  60. let navigationInProgress = false;
  61. // Monitor changes to window.location
  62. ['assign', 'replace', 'href'].forEach(property => {
  63. const original = window.location[property];
  64. if (typeof original === 'function') {
  65. window.location[property] = function(url) {
  66. if (!navigationInProgress && handleNavigation(url)) {
  67. navigationInProgress = true;
  68. setTimeout(() => {
  69. navigationInProgress = false;
  70. }, 0);
  71. return original.apply(this, arguments);
  72. }
  73. };
  74. } else {
  75. Object.defineProperty(window.location, property, {
  76. set: function(url) {
  77. if (!navigationInProgress && handleNavigation(url)) {
  78. navigationInProgress = true;
  79. setTimeout(() => {
  80. navigationInProgress = false;
  81. }, 0);
  82. return Reflect.set(window.location, property, url);
  83. }
  84. },
  85. get: function() {
  86. return original;
  87. },
  88. configurable: true
  89. });
  90. }
  91. });
  92. // Enhanced navigation control for back/forward buttons
  93. window.addEventListener('popstate', function(event) {
  94. if (!navigationInProgress && !isUrlAllowed(window.location.href)) {
  95. navigationInProgress = true;
  96. setTimeout(() => {
  97. navigationInProgress = false;
  98. }, 0);
  99. event.preventDefault();
  100. }
  101. });
  102. // Function to handle history manipulation
  103. function handleHistoryManipulation(originalMethod, data, title, url) {
  104. if (!isUrlAllowed(url)) {
  105. console.error('Blocked history manipulation to:', url);
  106. return;
  107. }
  108. return originalMethod(data, title, url);
  109. }
  110. // Wrap history.pushState and history.replaceState
  111. const originalPushState = history.pushState;
  112. const originalReplaceState = history.replaceState;
  113. history.pushState = function(data, title, url) {
  114. return handleHistoryManipulation.call(history, originalPushState.bind(this), data, title, url);
  115. };
  116. history.replaceState = function(data, title, url) {
  117. return handleHistoryManipulation.call(history, originalReplaceState.bind(this), data, title, url);
  118. };
  119. // Keyboard shortcut listener to display the blacklist
  120. document.addEventListener('keydown', function(e) {
  121. if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'l') {
  122. e.preventDefault();
  123. displayBlacklist();
  124. }
  125. });
  126. // Function to check if a URL is allowed based on the blacklist
  127. function isUrlAllowed(url) {
  128. let blacklist = getBlacklist();
  129. return !blacklist.has(url);
  130. }
  131. console.log('Redirect control script with blacklist initialized.');
  132. })();