Stop Nefarious Redirects

Block unauthorized redirects and prevent history manipulation

目前為 2024-05-28 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Stop Nefarious Redirects
  3. // @namespace http://tampermonkey.net/
  4. // @version 4.1
  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. const manualBlacklist = new Set([
  16. 'getrunkhomuto.info'
  17. ]);
  18.  
  19. // List of allowed popups domains
  20. const allowedPopups = [
  21. '500px.com', 'accuweather.com', 'adobe.com', 'adulttime.com', 'alibaba.com', 'amazon.com', 'amazonaws.com',
  22. 'amd.com', 'americanexpress.com', 'anaconda.com', 'angular.io', 'ap.org', 'apache.org', 'apnews.com',
  23. 'apple.com', 'arstechnica.com', 'artstation.com', 'asana.com', 'asus.com', 'atlassian.com', 'autodesk.com',
  24. 'axios.com', 'battle.net', 'bbc.co.uk', 'bbc.com', 'behance.net', 'bestbuy.com', 'bing.com', 'bitbucket.org',
  25. 'blogger.com', 'bloomberg.com', 'bmw.com', 'boeing.com', 'booking.co.uk', 'booking.com', 'bootstrapcdn.com',
  26. 'breitbart.com', 'buzzfeed.com', 'canva.com', 'capitalone.com', 'cbsnews.com', 'character.ai', 'chase.com',
  27. 'chaturbate.com', 'cisco.com', 'citi.com', 'cnbc.com', 'cnet.com', 'cnn.com', 'codecademy.com', 'constantcontact.com',
  28. 'coursera.org', 'craigslist.org', 'dailymail.co.uk', 'dell.com', 'deviantart.com', 'discord.com', 'disney.com',
  29. 'django.com', 'docker.com', 'docusign.com', 'dribbble.com', 'dropbox.com', 'duckduckgo.com', 'duolingo.com',
  30. 'duosecurity.com', 'ebay.com', 'economist.com', 'edx.org', 'elsevier.com', 'engadget.com', 'epicgames.com',
  31. 'eporner.com', 'espn.com', 'etsy.com', 'eurogamer.net', 'expedia.com', 'facebook.com', 'fandom.com', 'fedex.com',
  32. 'figma.com', 'finance.yahoo.com', 'flickr.com', 'flipkart.com', 'forbes.com', 'foxnews.com', 'framer.com',
  33. 'freecodecamp.org', 'gamespot.com', 'gartner.com', 'gettyimages.com', 'git-scm.com', 'github.com', 'gizmodo.com',
  34. 'go.com', 'godaddy.com', 'gog.com', 'goldmansachs.com', 'google.com', 'healthline.com', 'hilton.com', 'homedepot.com',
  35. 'hp.com', 'hubspot.com', 'huffpost.com', 'hulu.com', 'humblebundle.com', 'ibm.com', 'ieee.org', 'ifixit.com',
  36. 'ign.com', 'ikea.com', 'imdb.com', 'imgur.com', 'indeed.com', 'instagram.com', 'instructure.com', 'intel.com',
  37. 'intuit.com', 'invisionapp.com', 'itch.io', 'java.com', 'jetbrains.com', 'joomla.org', 'jquery.com', 'khanacademy.org',
  38. 'kotaku.com', 'kotlinlang.org', 'laravel.com', 'lenovo.com', 'lg.com', 'lifehacker.com', 'linkedin.com', 'live.com',
  39. 'lowes.com', 'lynda.com', 'macys.com', 'mailchimp.com', 'marriott.com', 'mashable.com', 'masterclass.com',
  40. 'mcdonalds.com', 'medium.com', 'mercedes-benz.com', 'microsoft.com', 'microsoftonline.commit.edu', 'mongodb.com',
  41. 'moodle.org', 'mozilla.org', 'msn.com', 'msnbc.com', 'nasa.gov', 'nationalgeographic.com', 'nbc.com', 'nbcnews.com',
  42. 'netflix.com', 'new.reddit.com', 'nextdoor.com', 'nih.gov', 'npr.org', 'nvidia.comnypost.com', 'nytimes.com',
  43. 'office.com', 'okta.com', 'onlyfans.com', 'openai.com', 'oracle.com', 'oreilly.com', 'origin.com', 'outlook.com',
  44. 'overstock.com', 'patreon.com', 'paypal.com', 'pcgamer.com', 'pexels.com', 'php.net', 'pinterest.com', 'pixabay.com',
  45. 'pluralsight.com', 'polygon.com', 'pornhub.com', 'python.org', 'quizlet.com', 'quora.com', 'reactjs.org', 'realtor.com',
  46. 'reddit.com', 'redhat.com', 'roblox.com', 'rubyonrails.org', 'salesforce.com', 'samsung.co.kr', 'samsung.com',
  47. 'sap.com', 'sciencedirect.com', 'scopus.com', 'sears.com', 'sharepoint.com', 'shutterstock.com', 'siemens.com',
  48. 'sketch.com', 'skillshare.com', 'skype.com', 'slack.com', 'sony.com', 'soundcloud.com', 'spotify.com', 'spring.io',
  49. 'stackoverflow.com', 'steamcommunity.com', 'steampowered.com', 'surveymonkey.com', 'symantec.com', 'target.com',
  50. 'techcrunch.com', 'temu.com', 'tesla.com', 'texasinstruments.com', 'theguardian.com', 'thenextweb.com', 'theverge.com',
  51. 'tiktok.com', 'time.com', 'toyota.com', 'trello.com', 'trip.com', 'tripadvisor.com', 'tumblr.com', 'twitch.tv',
  52. 'twitter.com', 'uber.com', 'ucla.edu', 'ucsf.edu', 'udemy.com', 'unity.com', 'unsplash.com', 'ups.com', 'usatoday.com',
  53. 'usnews.com', 'usps.com', 'verizon.com', 'Vice.com', 'vice.com', 'vimeo.com', 'vk.com', 'vmware.com', 'volkswagen.com',
  54. 'vox.com', 'walmart.com', 'washingtonpost.com', 'weather.com', 'weather.gov', 'webmd.com', 'whatsapp.com', 'wikimedia.org',
  55. 'wikipedia.org', 'wired.com', 'wordpress.com', 'wsj.com', 'wunderground.com', 'x.com', 'xerox.com', 'xfinity.com',
  56. 'yahoo.com', 'yelp.com', 'youtube.com', 'zapier.com', 'zendesk.com', 'zeplin.iozillow.com', 'zoom.us'
  57. ];
  58.  
  59. (function() {
  60. 'use strict';
  61.  
  62. console.log('Script initialization started.');
  63.  
  64. /**
  65. * Get the current automated blacklist
  66. * @returns {Set} The automated blacklist
  67. */
  68. function getAutomatedBlacklist() {
  69. return new Set(GM_getValue('blacklist', []));
  70. }
  71.  
  72. /**
  73. * Add a URL to the automated blacklist
  74. * @param {string} url - The URL to add to the blacklist
  75. */
  76. function addToAutomatedBlacklist(url) {
  77. const encodedUrl = encodeURIComponent(url);
  78. const blacklist = getAutomatedBlacklist();
  79. if (!blacklist.has(encodedUrl)) {
  80. blacklist.add(encodedUrl);
  81. GM_setValue('blacklist', Array.from(blacklist));
  82. console.log('Added to automated blacklist:', url);
  83. }
  84. }
  85.  
  86. /**
  87. * Check if navigation to a URL is allowed
  88. * @param {string} url - The URL to check
  89. * @returns {boolean} True if navigation is allowed, false otherwise
  90. */
  91. function isNavigationAllowed(url) {
  92. if (!isUrlBlocked(url)) {
  93. console.log('Navigation allowed to:', url);
  94. lastKnownGoodUrl = url;
  95. return true;
  96. } else {
  97. console.error('Blocked navigation to:', url);
  98. addToAutomatedBlacklist(url);
  99. if (lastKnownGoodUrl) {
  100. window.location.replace(lastKnownGoodUrl);
  101. }
  102. return false;
  103. }
  104. }
  105.  
  106. const originalAssign = window.location.assign.bind(window.location);
  107. const originalOpen = window.open;
  108.  
  109. console.log('Original window.location.assign and window.open saved.');
  110.  
  111. window.location.assign = function(url) {
  112. console.log('Redirect attempt detected:', url);
  113. if (!allowedPopups.some(domain => url.includes(domain)) && !isNavigationAllowed(url)) {
  114. console.log('Redirect to undesired domain blocked:', url);
  115. return;
  116. }
  117. console.log('Redirect allowed to:', url);
  118. return originalAssign(url);
  119. };
  120.  
  121. console.log('window.location.assign overridden with custom logic.');
  122.  
  123. window.open = function(url, name, features) {
  124. console.log('Popup attempt detected:', url);
  125. if (allowedPopups.some(domain => url.includes(domain)) || isNavigationAllowed(url)) {
  126. console.log('Popup allowed for:', url);
  127. return originalOpen(url, name, features);
  128. }
  129. console.log('Blocked a popup from:', url);
  130. return null;
  131. };
  132.  
  133. console.log('window.open overridden with custom logic.');
  134.  
  135. let lastKnownGoodUrl = window.location.href;
  136.  
  137. const locationProxy = new Proxy(window.location, {
  138. set(target, prop, value) {
  139. if (prop === 'href' || prop === 'assign' || prop === 'replace') {
  140. if (!isNavigationAllowed(value)) {
  141. return false;
  142. }
  143. }
  144. return Reflect.set(target, prop, value);
  145. },
  146. get(target, prop) {
  147. if (prop === 'assign' || prop === 'replace') {
  148. return function(url) {
  149. if (isNavigationAllowed(url)) {
  150. return target[prop].call(target, url);
  151. }
  152. };
  153. }
  154. return Reflect.get(target, prop);
  155. }
  156. });
  157.  
  158. Object.defineProperty(window, 'location', {
  159. configurable: true,
  160. enumerable: true,
  161. get() {
  162. return locationProxy;
  163. }
  164. });
  165.  
  166. window.addEventListener('popstate', function(event) {
  167. if (!isNavigationAllowed(window.location.href)) {
  168. console.error('Blocked navigation to:', window.location.href);
  169. history.pushState(null, "", lastKnownGoodUrl);
  170. window.location.replace(lastKnownGoodUrl);
  171. event.preventDefault();
  172. }
  173. });
  174.  
  175. /**
  176. * Handle history manipulation
  177. * @param {Function} originalMethod - The original history method
  178. * @param {*} data - The state data
  179. * @param {string} title - The page title
  180. * @param {string|null} url - The URL
  181. * @returns {*} The result of calling the original method
  182. */
  183. function handleHistoryManipulation(originalMethod, data, title, url) {
  184. if (!isUrlBlocked(url)) {
  185. return originalMethod.call(history, data, title, url);
  186. }
  187. console.error('Blocked history manipulation to:', url);
  188. }
  189.  
  190. const originalPushState = history.pushState;
  191. const originalReplaceState = history.replaceState;
  192.  
  193. history.pushState = function(data, title, url) {
  194. return handleHistoryManipulation(originalPushState, data, title, url);
  195. };
  196.  
  197. history.replaceState = function(data, title, url) {
  198. return handleHistoryManipulation(originalReplaceState, data, title, url);
  199. };
  200.  
  201. /**
  202. * Check if a URL is blocked based on the blacklist
  203. * @param {string} url - The URL to check
  204. * @returns {boolean} True if the URL is blocked, false otherwise
  205. */
  206. function isUrlBlocked(url) {
  207. const encodedUrl = encodeURIComponent(url);
  208. const automatedBlacklist = getAutomatedBlacklist();
  209. const isBlocked = [...manualBlacklist, ...automatedBlacklist].some(blockedUrl => encodedUrl.includes(blockedUrl));
  210. if (isBlocked) {
  211. console.log(`Blocked URL: ${url}`);
  212. }
  213. return isBlocked;
  214. }
  215.  
  216. console.log('Redirect control script with blacklist initialized.');
  217. })();