fix: split stealth init scripts by browser engine and add Firefox stealth
The stealth system previously injected all 12 init scripts unconditionally into every browser engine. Chromium-specific scripts (window.chrome stubs, ANGLE WebGL strings, CDP cleanup, HeadlessChrome UA strip) were no-ops or actively suspicious on Firefox, while Firefox-specific headless vectors were unaddressed. Split stealthInitScripts into three categories: - stealthCommonScripts (4): webdriver, outerWidth/Height, permissions, Notification - stealthChromiumScripts (8): existing Chromium-specific scripts - stealthFirefoxScripts (5): new Firefox-specific stealth: - navigator.webdriver getOwnPropertyDescriptor hardening - WebGL renderer spoof with Mesa/Intel strings - mozInnerScreenX/Y non-zero spoof - navigator.hardwareConcurrency normalization - PDF.js plugin list override browser_init.go now selects common + engine-specific scripts based on opt.Browser. Tests updated with per-category validation and cross- contamination checks. Closes #69 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
270
stealth_test.go
270
stealth_test.go
@@ -66,105 +66,311 @@ func TestStealthChromiumArgs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts(t *testing.T) {
|
||||
if len(stealthInitScripts) == 0 {
|
||||
t.Fatal("expected at least one stealth init script")
|
||||
// --- Common scripts ---
|
||||
|
||||
func TestStealthCommonScripts_Count(t *testing.T) {
|
||||
if len(stealthCommonScripts) != 4 {
|
||||
t.Fatalf("expected 4 common stealth scripts, got %d", len(stealthCommonScripts))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_Count(t *testing.T) {
|
||||
if len(stealthInitScripts) != 12 {
|
||||
t.Fatalf("expected 12 stealth init scripts, got %d", len(stealthInitScripts))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_WebGLSpoof(t *testing.T) {
|
||||
func TestStealthCommonScripts_WebdriverOverride(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
if strings.Contains(s, "SwiftShader") || strings.Contains(s, "UNMASKED_RENDERER") || strings.Contains(s, "37446") {
|
||||
for _, s := range stealthCommonScripts {
|
||||
if strings.Contains(s, "navigator") && strings.Contains(s, "webdriver") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that spoofs WebGL renderer")
|
||||
t.Fatal("expected a common script that overrides navigator.webdriver")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_ChromeApp(t *testing.T) {
|
||||
func TestStealthCommonScripts_OuterDimensions(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
if strings.Contains(s, "chrome.app") && strings.Contains(s, "chrome.csi") && strings.Contains(s, "chrome.loadTimes") {
|
||||
for _, s := range stealthCommonScripts {
|
||||
if strings.Contains(s, "outerWidth") && strings.Contains(s, "outerHeight") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that stubs chrome.app, chrome.csi, and chrome.loadTimes")
|
||||
t.Fatal("expected a common script that fixes outerWidth/outerHeight")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_PermissionsQuery(t *testing.T) {
|
||||
func TestStealthCommonScripts_PermissionsQuery(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
for _, s := range stealthCommonScripts {
|
||||
if strings.Contains(s, "permissions.query") && strings.Contains(s, "notifications") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that overrides permissions.query for notifications")
|
||||
t.Fatal("expected a common script that overrides permissions.query for notifications")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_Notification(t *testing.T) {
|
||||
func TestStealthCommonScripts_Notification(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
for _, s := range stealthCommonScripts {
|
||||
if strings.Contains(s, "Notification") && strings.Contains(s, "requestPermission") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that stubs Notification constructor")
|
||||
t.Fatal("expected a common script that stubs Notification constructor")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_NavigatorConnection(t *testing.T) {
|
||||
// --- Chromium scripts ---
|
||||
|
||||
func TestStealthChromiumScripts_Count(t *testing.T) {
|
||||
if len(stealthChromiumScripts) != 8 {
|
||||
t.Fatalf("expected 8 chromium stealth scripts, got %d", len(stealthChromiumScripts))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_Plugins(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "Chrome PDF Plugin") && strings.Contains(s, "navigator") && strings.Contains(s, "plugins") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a chromium script that populates navigator.plugins with Chrome entries")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_MimeTypes(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "mimeTypes") && strings.Contains(s, "application/pdf") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a chromium script that populates navigator.mimeTypes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_WindowChrome(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "window.chrome") && strings.Contains(s, "runtime") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a chromium script that stubs window.chrome")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_ChromeApp(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "chrome.app") && strings.Contains(s, "chrome.csi") && strings.Contains(s, "chrome.loadTimes") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a chromium script that stubs chrome.app, chrome.csi, and chrome.loadTimes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_WebGLSpoof(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "37446") && strings.Contains(s, "ANGLE") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a chromium script that spoofs WebGL renderer with ANGLE strings")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_NavigatorConnection(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "connection") && strings.Contains(s, "effectiveType") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that stubs navigator.connection")
|
||||
t.Fatal("expected a chromium script that stubs navigator.connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_CDPCleanup(t *testing.T) {
|
||||
func TestStealthChromiumScripts_CDPCleanup(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "cdc_") && strings.Contains(s, "delete") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that cleans up CDP artifacts")
|
||||
t.Fatal("expected a chromium script that cleans up CDP artifacts")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthInitScripts_UserAgentStrip(t *testing.T) {
|
||||
func TestStealthChromiumScripts_UserAgentStrip(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthInitScripts {
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if strings.Contains(s, "HeadlessChrome") && strings.Contains(s, "userAgent") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a stealth script that strips HeadlessChrome from user agent")
|
||||
t.Fatal("expected a chromium script that strips HeadlessChrome from user agent")
|
||||
}
|
||||
}
|
||||
|
||||
// --- Firefox scripts ---
|
||||
|
||||
func TestStealthFirefoxScripts_Count(t *testing.T) {
|
||||
if len(stealthFirefoxScripts) != 5 {
|
||||
t.Fatalf("expected 5 firefox stealth scripts, got %d", len(stealthFirefoxScripts))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_WebdriverHardening(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if strings.Contains(s, "getOwnPropertyDescriptor") && strings.Contains(s, "webdriver") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a firefox script that hardens navigator.webdriver via getOwnPropertyDescriptor")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_WebGLSpoof(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if strings.Contains(s, "37446") && strings.Contains(s, "Mesa DRI") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a firefox script that spoofs WebGL renderer with Mesa strings")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_MozInnerScreen(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if strings.Contains(s, "mozInnerScreenX") && strings.Contains(s, "mozInnerScreenY") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a firefox script that spoofs mozInnerScreenX/mozInnerScreenY")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_HardwareConcurrency(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if strings.Contains(s, "hardwareConcurrency") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a firefox script that normalizes navigator.hardwareConcurrency")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_PDFjsPlugins(t *testing.T) {
|
||||
found := false
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if strings.Contains(s, "PDF.js") && strings.Contains(s, "plugins") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected a firefox script that provides PDF.js plugin entry")
|
||||
}
|
||||
}
|
||||
|
||||
// --- Cross-category validation ---
|
||||
|
||||
func TestStealthScripts_NoOverlap(t *testing.T) {
|
||||
all := make(map[string]string) // script -> category
|
||||
for _, s := range stealthCommonScripts {
|
||||
all[s] = "common"
|
||||
}
|
||||
for _, s := range stealthChromiumScripts {
|
||||
if cat, ok := all[s]; ok {
|
||||
t.Fatalf("chromium script also appears in %s category", cat)
|
||||
}
|
||||
all[s] = "chromium"
|
||||
}
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
if cat, ok := all[s]; ok {
|
||||
t.Fatalf("firefox script also appears in %s category", cat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthCommonScripts_NoChromiumMarkers(t *testing.T) {
|
||||
chromiumMarkers := []string{"window.chrome", "chrome.app", "chrome.csi", "chrome.loadTimes", "HeadlessChrome", "cdc_", "Chrome PDF Plugin", "ANGLE"}
|
||||
for _, s := range stealthCommonScripts {
|
||||
for _, marker := range chromiumMarkers {
|
||||
if strings.Contains(s, marker) {
|
||||
t.Fatalf("common script contains Chromium-specific marker %q", marker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthCommonScripts_NoFirefoxMarkers(t *testing.T) {
|
||||
firefoxMarkers := []string{"mozInnerScreen", "Mesa DRI", "PDF.js"}
|
||||
for _, s := range stealthCommonScripts {
|
||||
for _, marker := range firefoxMarkers {
|
||||
if strings.Contains(s, marker) {
|
||||
t.Fatalf("common script contains Firefox-specific marker %q", marker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthChromiumScripts_NoFirefoxMarkers(t *testing.T) {
|
||||
firefoxMarkers := []string{"mozInnerScreen", "Mesa DRI", "PDF.js"}
|
||||
for _, s := range stealthChromiumScripts {
|
||||
for _, marker := range firefoxMarkers {
|
||||
if strings.Contains(s, marker) {
|
||||
t.Fatalf("chromium script contains Firefox-specific marker %q", marker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStealthFirefoxScripts_NoChromiumMarkers(t *testing.T) {
|
||||
chromiumMarkers := []string{"window.chrome", "chrome.app", "chrome.csi", "chrome.loadTimes", "HeadlessChrome", "cdc_", "Chrome PDF Plugin", "ANGLE"}
|
||||
for _, s := range stealthFirefoxScripts {
|
||||
for _, marker := range chromiumMarkers {
|
||||
if strings.Contains(s, marker) {
|
||||
t.Fatalf("firefox script contains Chromium-specific marker %q", marker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user