mirror of
https://github.com/daijro/camoufox.git
synced 2026-09-09 00:00:39 +00:00
Camoufox applies a per-context fingerprint through fifteen helpers on window
-- setNavigatorPlatform(), setTimezone(), setWebGLRenderer() and the rest.
Each removed itself from window when called, which only ever covered the
setters a given fingerprint happened to set:
* a value the config left alone never called its setter, so setTimezone (no
timezone configured) and setWebRTCIPv6 (never emitted by any code path)
stayed on window for every context;
* a launch that registers no init script at all left all fifteen. That is
Camoufox() followed by browser.new_page(), the documented default, where
the fingerprint comes from CAMOU_CONFIG in C++ and nothing ever touches a
setter;
* so did launching the binary as a plain browser, with no juggler running.
Page script could not only see them but call them: window.setNavigator-
HardwareConcurrency(999) from a page moved navigator.hardwareConcurrency to
999. Fifteen window properties no other Firefox build has is a sharper
fingerprint than any of the values they were hiding.
A window is now created sealed and juggler opens it for exactly as long as
init scripts are running:
window created -> sealed -> unseal -> init scripts apply the fingerprint
-> seal -> page script runs, setters gone
Sealed by default so the failure is closed: a path that does not go through
juggler never offers the setters, rather than offering them permanently.
Per *window*, not per browsing context. A context-wide flag -- which is what
the existing self-destruct effectively was -- fires on the initial about:blank
and leaves every later navigation unable to apply anything, so both contexts
come up with the launch-level fingerprint instead of their own. The regression
test covers that case.
Deleting the names is not on its own enough: they are handed out lazily by the
DOM resolve hook, so a deleted name comes straight back. The Func= guards
consult the seal, which is what makes the deletion stick; the delete clears
what the init script's `typeof w.setX === "function"` probe already
materialised.
build-tester scored this A throughout because its checklist omitted
setNavigatorUserAgent and setWebRTCIPv6 -- the two that leaked on every
context -- while asserting the absence of setCanvasSeed, which has never
existed anywhere in the tree and so passed vacuously.
Measured on Linux x86_64, beta.30 vs the shipped beta.29:
path before after
Camoufox() + new_context() 15 0
context with an init script 2 0
page.add_init_script() after new_page 15 0
binary launched with no juggler 15 0
Fingerprints still apply as requested in every case. tests/patches 7/7,
build-tester 962/962.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018i4WFSwSGLNH2d7wVVKFjQ
Camoufox Tests
Ensures that Playwright functionality is not broken.
This directory is based on the original Playwright-Python tests.
It has been modified to skip tests that use the following features:
- Injecting JavaScript into the page or writing to DOM. Camoufox's
page.evaluateonly supports reading values, not executing within the page context. - Overriding the User-Agent.
- Any tests specific to Chromium or Webkit.
Usage
Setting up the environment
Cd to this directory and run the following command to setup the venv and install the dependencies:
bash setup-venv.sh
Running the tests
Run via the shell script:
bash run-tests.sh --headful --executable-path /path/to/camoufox-bin
Or through the Makefile:
make tests headful=true