chore(release): 0.27.0-fork.30 — stealth: navigator overrides on prototype, not instance
Release binaries / Build macOS ARM64 (push) Has been cancelled
Release binaries / Build macOS x64 (push) Has been cancelled
Release binaries / Build Linux ARM64 (push) Has been cancelled
Release binaries / Build Linux musl ARM64 (push) Has been cancelled
Release binaries / Build Linux musl x64 (push) Has been cancelled
Release binaries / Build Linux x64 (push) Has been cancelled
Release binaries / Build Windows x64 (push) Has been cancelled
Release binaries / Attach binaries to GitHub Release (push) Has been cancelled
Release binaries / Build macOS ARM64 (push) Has been cancelled
Release binaries / Build macOS x64 (push) Has been cancelled
Release binaries / Build Linux ARM64 (push) Has been cancelled
Release binaries / Build Linux musl ARM64 (push) Has been cancelled
Release binaries / Build Linux musl x64 (push) Has been cancelled
Release binaries / Build Linux x64 (push) Has been cancelled
Release binaries / Build Windows x64 (push) Has been cancelled
Release binaries / Attach binaries to GitHub Release (push) Has been cancelled
rebrowser's navigatorWebdriver probe checks Object.getOwnPropertyNames(navigator) == [] (real Chrome keeps navigator members on Navigator.prototype). The launch-mode stealth script defined language/languages/userAgentData/contacts as instance own-properties, leaking them as an automation tell. - add __abRedefineNavProto(name, getterImpl): redefines a navigator member on the PROTOTYPE with a native-masked getter toString, then deletes any instance shadow (mirrors the existing vendor patch). Falls back to instance only if proto is locked. - convert language/languages/userAgentData to it; make the contacts block prototype-first. After: Object.getOwnPropertyNames(navigator) == [], values intact, getters native, rebrowser navigatorWebdriver 🟢, runtimeEnableLeak/pwInitScripts 🟢, sannysoft 0 fails.
This commit is contained in:
Generated
+1
-1
@@ -45,7 +45,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.29"
|
version = "0.27.0-fork.30"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.29"
|
version = "0.27.0-fork.30"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Fast browser automation CLI for AI agents"
|
description = "Fast browser automation CLI for AI agents"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -1,4 +1,31 @@
|
|||||||
const __abStealth = { locale: "en-US", languages: ["en-US", "en"], allowWebGLContextFallback: false, hideCanvas: false, canvasSeed: 0 };
|
const __abStealth = { locale: "en-US", languages: ["en-US", "en"], allowWebGLContextFallback: false, hideCanvas: false, canvasSeed: 0 };
|
||||||
|
// Redefine a navigator property on its PROTOTYPE (Navigator / WorkerNavigator),
|
||||||
|
// the way real Chrome exposes these — as prototype getters, NOT instance own
|
||||||
|
// properties. Adding an own property to the `navigator` instance is itself a
|
||||||
|
// detectable automation tell: real Chrome's `Object.getOwnPropertyNames(navigator)`
|
||||||
|
// is empty, so any name we leave on the instance is caught by rebrowser's
|
||||||
|
// `navigatorWebdriver` probe and similar checks. We mirror the proven `vendor`
|
||||||
|
// patch below: define on the prototype, native-mask the getter's toString, then
|
||||||
|
// delete any instance shadow. Falls back to an instance define only if the
|
||||||
|
// prototype is locked. (A top-level `const` like this is script-scoped, not a
|
||||||
|
// `window` property, so it does not leak — same as `__abStealth` above.)
|
||||||
|
const __abRedefineNavProto = (name, getterImpl) => {
|
||||||
|
try {
|
||||||
|
const proto = Object.getPrototypeOf(navigator);
|
||||||
|
const nativeGet = Object.getOwnPropertyDescriptor(proto, name) && Object.getOwnPropertyDescriptor(proto, name).get;
|
||||||
|
const getter = function () { return getterImpl(); };
|
||||||
|
if (nativeGet) {
|
||||||
|
Object.defineProperty(getter, 'name', { value: 'get ' + name, configurable: true });
|
||||||
|
Object.defineProperty(getter, 'toString', { value: () => nativeGet.toString(), configurable: true, writable: true });
|
||||||
|
}
|
||||||
|
Object.defineProperty(proto, name, { get: getter, configurable: true, enumerable: true });
|
||||||
|
try { delete navigator[name]; } catch (e) {}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
try { Object.defineProperty(navigator, name, { get: () => getterImpl(), configurable: true }); } catch (e2) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
(function(){
|
(function(){
|
||||||
// Prefer the CDP-level automation override (Emulation.setAutomationOverride),
|
// Prefer the CDP-level automation override (Emulation.setAutomationOverride),
|
||||||
// which makes navigator.webdriver report `false` NATIVELY — undetectable by
|
// which makes navigator.webdriver report `false` NATIVELY — undetectable by
|
||||||
@@ -354,18 +381,8 @@ const __abStealth = { locale: "en-US", languages: ["en-US", "en"], allowWebGLCon
|
|||||||
const config = (typeof __abStealth === 'object' && __abStealth) ? __abStealth : null;
|
const config = (typeof __abStealth === 'object' && __abStealth) ? __abStealth : null;
|
||||||
if (!config || !Array.isArray(config.languages) || config.languages.length === 0) return;
|
if (!config || !Array.isArray(config.languages) || config.languages.length === 0) return;
|
||||||
const locale = typeof config.locale === 'string' ? config.locale : config.languages[0];
|
const locale = typeof config.locale === 'string' ? config.locale : config.languages[0];
|
||||||
try {
|
__abRedefineNavProto('language', () => locale);
|
||||||
Object.defineProperty(navigator, 'language', {
|
__abRedefineNavProto('languages', () => config.languages.slice());
|
||||||
get: () => locale,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
} catch {}
|
|
||||||
try {
|
|
||||||
Object.defineProperty(navigator, 'languages', {
|
|
||||||
get: () => config.languages.slice(),
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
} catch {}
|
|
||||||
})();
|
})();
|
||||||
(function(){
|
(function(){
|
||||||
const ua = String(navigator.userAgent || '');
|
const ua = String(navigator.userAgent || '');
|
||||||
@@ -1055,10 +1072,15 @@ const __abStealth = { locale: "en-US", languages: ["en-US", "en"], allowWebGLCon
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (defineContacts(navigator)) return;
|
// Prototype-first (like the vendor patch): real Chrome exposes navigator
|
||||||
try {
|
// members on the prototype, not as instance own properties. Define on the
|
||||||
defineContacts(Object.getPrototypeOf(navigator));
|
// prototype and remove any instance shadow so Object.getOwnPropertyNames(navigator)
|
||||||
} catch {}
|
// stays empty; fall back to the instance only if the prototype is locked.
|
||||||
|
if (defineContacts(Object.getPrototypeOf(navigator))) {
|
||||||
|
try { delete navigator.contacts; } catch {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defineContacts(navigator);
|
||||||
})();
|
})();
|
||||||
(function(){
|
(function(){
|
||||||
const ContentIndexCtor = typeof ContentIndex === 'function'
|
const ContentIndexCtor = typeof ContentIndex === 'function'
|
||||||
@@ -1265,12 +1287,7 @@ const __abStealth = { locale: "en-US", languages: ["en-US", "en"], allowWebGLCon
|
|||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
};
|
};
|
||||||
try {
|
__abRedefineNavProto('userAgentData', () => patched);
|
||||||
Object.defineProperty(navigator, 'userAgentData', {
|
|
||||||
get: () => patched,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
} catch {}
|
|
||||||
})();
|
})();
|
||||||
(function(){
|
(function(){
|
||||||
const ua = navigator.userAgent;
|
const ua = navigator.userAgent;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agent-browser-stealth",
|
"name": "agent-browser-stealth",
|
||||||
"version": "0.27.0-fork.29",
|
"version": "0.27.0-fork.30",
|
||||||
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@11.1.3",
|
"packageManager": "pnpm@11.1.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user