Skip to content

feat(plugins): add stealth plugin (WebRTC block, locale/TZ/geo overrides)#3109

Open
dawsman wants to merge 1 commit into
jo-inc:masterfrom
dawsman:feat/stealth-plugin
Open

feat(plugins): add stealth plugin (WebRTC block, locale/TZ/geo overrides)#3109
dawsman wants to merge 1 commit into
jo-inc:masterfrom
dawsman:feat/stealth-plugin

Conversation

@dawsman
Copy link
Copy Markdown

@dawsman dawsman commented May 13, 2026

What

Adds a new plugins/stealth/ that closes the two most common fingerprint leaks visible on creepjs / sannysoft / browserleaks when running without a residential proxy:

  1. WebRTC IP leak — disables media.peerconnection.enabled plus tightens ICE so even if a downstream consumer flips WebRTC back on, host candidates can't reveal the host IP.
  2. Hardcoded LA / en-US / SF context defaultssession:creating is already where these live in server.js (~line 781); the plugin lets you point locale / timezone / geolocation anywhere via config or env.

Both knobs are no-ops when their respective config keys are unset, so enabling the plugin with empty config gets you a WebRTC-blocked browser and nothing else changes.

Default is "enabled": false in camofox.config.json — opt-in, no behavior change on upgrade.

Verified

CreepJS headless score on a default camofox instance drops from 13% → 0% after enabling stealth + a UK config. WebRTC host / srflx candidates become empty (blocked) on browserleaks/webrtc. Timezone and locale on creepjs match the configured values.

Tests

plugins/stealth/plugin.test.js — 9 tests covering:

  • WebRTC block on/off, env override
  • Accept-Language set / passthrough
  • locale / timezone / geolocation override
  • env precedence over plugin config
  • passthrough when nothing configured
  • partial config (one knob set, others passthrough)

All 35 plugin tests across plugins/** pass.

Limitation (called out in README + AGENTS)

The browser:launching hook fires after camoufox-js's launchOptions() has already baked the os choice into Playwright launch args, so this plugin can't change navigator.platform, the UA family, or WebGL renderer — those depend on core picking a different os value upstream of this hook. Documenting so a future contributor doesn't waste time trying.

🤖 Generated with Claude Code

…des)

Closes the two most common fingerprint leaks visible on creepjs /
sannysoft / browserleaks when running without a residential proxy:

1. WebRTC IP leak — disables media.peerconnection.enabled plus tightens
   ICE so even if a downstream consumer flips WebRTC back on, host
   candidates can't reveal the host IP.
2. The hardcoded LA/en-US/SF context defaults (server.js ~line 781) —
   the plugin lets you point locale / timezoneId / geolocation anywhere
   via plugin config or env vars (CAMOFOX_STEALTH_LOCALE,
   CAMOFOX_STEALTH_TZ, CAMOFOX_STEALTH_GEO_LAT/LON,
   CAMOFOX_STEALTH_BLOCK_WEBRTC).

Both knobs are no-ops when their respective config keys are unset, so
enabling stealth with empty config gets you a WebRTC-blocked browser
and nothing else changes.

Default is `"enabled": false` in camofox.config.json — opt-in, no
behavior change for existing users on upgrade.

CreepJS headless score on a default install drops 13% -> 0% after
enabling stealth + a UK config. WebRTC host/srflx candidates become
empty on browserleaks/webrtc. Timezone/locale on creepjs match the
configured values.

Limitation: the browser:launching hook fires after camoufox-js's
launchOptions() has already baked the `os` choice into Playwright
launch args, so this plugin can't change navigator.platform, the UA
family, or WebGL renderer — those depend on core picking a different
`os` value upstream of this hook.

Tests: plugins/stealth/plugin.test.js — 9 tests covering WebRTC on/off,
env-over-config precedence, partial config, and passthrough. All 35
plugin tests across plugins/** still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant