fix: add stealth measures to bypass Teams bot detection (webdriver, plugins, chrome.runtime)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f5be3f886e
commit
d3f8457c42
1 changed files with 37 additions and 0 deletions
|
|
@ -545,6 +545,7 @@ export class BotOrchestrator {
|
|||
'--disable-web-security',
|
||||
'--disable-features=IsolateOrigins,site-per-process',
|
||||
'--autoplay-policy=no-user-gesture-required',
|
||||
'--disable-blink-features=AutomationControlled', // Prevent navigator.webdriver=true
|
||||
],
|
||||
});
|
||||
|
||||
|
|
@ -556,6 +557,42 @@ export class BotOrchestrator {
|
|||
|
||||
this._page = await this._context.newPage();
|
||||
|
||||
// Stealth: Override browser properties that reveal automation.
|
||||
// Teams checks these to detect headless/automated browsers and
|
||||
// blocks the /v2/ authenticated experience, falling back to light-meetings.
|
||||
await this._page.addInitScript(() => {
|
||||
// 1. Remove navigator.webdriver flag (primary detection signal)
|
||||
Object.defineProperty(navigator, 'webdriver', { get: () => false });
|
||||
|
||||
// 2. Add realistic plugins (headless has empty plugins array)
|
||||
Object.defineProperty(navigator, 'plugins', {
|
||||
get: () => [
|
||||
{ name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },
|
||||
{ name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' },
|
||||
{ name: 'Native Client', filename: 'internal-nacl-plugin', description: '' },
|
||||
],
|
||||
});
|
||||
|
||||
// 3. Add realistic languages
|
||||
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en', 'de'] });
|
||||
|
||||
// 4. Override permissions query to not reveal automation
|
||||
const originalQuery = window.navigator.permissions.query.bind(window.navigator.permissions);
|
||||
// @ts-ignore
|
||||
window.navigator.permissions.query = (parameters: any) => {
|
||||
if (parameters.name === 'notifications') {
|
||||
return Promise.resolve({ state: Notification.permission } as PermissionStatus);
|
||||
}
|
||||
return originalQuery(parameters);
|
||||
};
|
||||
|
||||
// 5. Add chrome runtime (missing in headless)
|
||||
// @ts-ignore
|
||||
if (!window.chrome) { window.chrome = {}; }
|
||||
// @ts-ignore
|
||||
if (!window.chrome.runtime) { window.chrome.runtime = {}; }
|
||||
});
|
||||
|
||||
// Initialize procedures
|
||||
const isAuthenticated = !!(this._options.botAccountEmail && this._options.botAccountPassword);
|
||||
this._joinProcedure = new JoinProcedure(this._page, this._logger, this._botName, isAuthenticated);
|
||||
|
|
|
|||
Loading…
Reference in a new issue