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-web-security',
|
||||||
'--disable-features=IsolateOrigins,site-per-process',
|
'--disable-features=IsolateOrigins,site-per-process',
|
||||||
'--autoplay-policy=no-user-gesture-required',
|
'--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();
|
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
|
// Initialize procedures
|
||||||
const isAuthenticated = !!(this._options.botAccountEmail && this._options.botAccountPassword);
|
const isAuthenticated = !!(this._options.botAccountEmail && this._options.botAccountPassword);
|
||||||
this._joinProcedure = new JoinProcedure(this._page, this._logger, this._botName, isAuthenticated);
|
this._joinProcedure = new JoinProcedure(this._page, this._logger, this._botName, isAuthenticated);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue