Chrome扩展注入JS修改navigator.webdriver失效问题排查
你的问题根源在于content script的沙箱隔离机制:你在content script里修改的navigator只是content script自身上下文的副本,页面全局的navigator对象完全没被改动——这就是为什么页面加载后,Selenium检测还是能读到true的原因。
下面是具体的修复方案:
1. 重构注入脚本,修改页面全局上下文的navigator
修改你的injected-javascript.js,通过注入script标签的方式,把代码直接运行在页面的全局环境中,而不是在content script的沙箱里:
// 要注入到页面全局的代码 const antiDetectScript = ` // 重定义webdriver属性,强制返回false Object.defineProperty(navigator, 'webdriver', { get: () => false, enumerable: true, configurable: false // 防止属性被后续代码重新定义 }); // 针对某些网站的深层检测,额外处理wrappedJSObject(Chrome特殊环境下的包装对象) if (navigator.wrappedJSObject) { Object.defineProperty(navigator.wrappedJSObject, 'webdriver', { get: () => false, enumerable: true, configurable: false }); } // 拦截任何试图修改webdriver的操作 Object.defineProperty(navigator, 'webdriver', { set: () => {}, // 忽略所有设置该属性的尝试 }); `; // 创建script标签注入到页面最开头,确保在页面任何脚本运行前生效 const scriptEl = document.createElement('script'); scriptEl.textContent = antiDetectScript; document.documentElement.insertBefore(scriptEl, document.documentElement.firstChild); // 注入后移除标签,清理DOM scriptEl.remove(); // 同时修改content script自身上下文的navigator,确保扩展内部检测也返回false Object.defineProperty(navigator, 'webdriver', { get: () => false, });
2. 优化Manifest配置,确保全局注入
更新你的manifest.json,添加all_frames: true确保所有嵌套iframe也能被注入,同时保留document_start的最早注入时机:
{ "manifest_version": 2, "name": "webdriverInjector", "version": "1.0.0", "content_scripts": [ { "matches": ["*://*/*"], "js": ["injected-javascript.js"], "run_at": "document_start", "all_frames": true // 覆盖所有页面层级 } ], "permissions": ["*://*/*"] }
3. 配合Selenium启动参数增强防护
如果你的Chrome版本在88以上,还可以添加Selenium启动参数,进一步绕过Chrome的原生自动化检测:
# Python Selenium示例 from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() # 加载你的未打包扩展(替换为你的扩展文件夹路径) chrome_options.add_argument('--load-extension=/path/to/your/unpacked-extension') # 禁用Chrome的自动化控制检测 chrome_options.add_argument('--disable-blink-features=AutomationControlled') # 解决某些环境下的沙箱限制 chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') driver = webdriver.Chrome(options=chrome_options)
验证方法
启动Selenium后,在页面控制台输入navigator.webdriver,应该返回false;或者在页面中执行以下代码确认:
console.log('navigator.webdriver:', navigator.webdriver);
这样修改后,页面全局的navigator.webdriver会被强制设为false,无论是页面自身的脚本还是Selenium的检测逻辑,都会读取到这个值。
内容的提问来源于stack exchange,提问作者RazorMx




