Comparison
Page, extension or engine
Three depths of one change
A value a site reads can be changed in three places. In the page over an answer that already exists, in an extension that reaches the page earlier, or in the engine that produces the answer.
These are not three degrees of the same thing. They differ in how much else has to agree with the change.
In the page
A property is replaced after the browser has prepared its answer.
In an extension
The same replacement, delivered before the page runs its own first script.
In the engine
The value is produced this way, so there is nothing left to replace.
What arrives over a ready answer
A script placed in the page's own world at document start is the earliest a page level layer can be, and it does arrive before the page asks anything.
It is still a correction laid over a value the browser already produced. The original does not go away: it stays reachable wherever the correction did not reach.
What a second realm answers
A page does not have to ask the document. It can open a background worker or an invisible frame and read the device there instead.
A page level layer only covers the realms it was installed into. Measured on such a layer: the document answered with the profile while a background worker answered with the machine below it.
The document
The realm every simple check reads, and the one a page level layer covers first.
An invisible frame
A child realm with its own copy of the same objects.
A background worker
A realm with no document, which a correction written for a document cannot reach.
Eight ways at their own depth
Read the table as scope rather than as a score. An empty cell means the question does not apply to that way of working.
The last row is ours. Every cell in it comes from code you can open or from the acceptance run of the built engine.
| Where the change is made | When it arrives | What a worker or a frame reads | What a mistake costs | |
|---|---|---|---|---|
| An ordinary browser as it is | No change is made | The same answers as the document | Nothing to get wrong | |
| Incognito | In the storage, not in the device | When the window opens | The machine's own answers | Nothing to get wrong |
| Separate profiles of the same browser | In the data directory on disk | At launch | The machine's own answers | Nothing to get wrong |
| An extension that swaps values in the page | In the page, over the real answer | Before the page's own first script | Whatever the layer reached, and the machine everywhere else | A relaunch to fix, and a replaced property to be read |
| A VPN | On the route, outside the browser | Before the first request leaves | Device answers are untouched | A reconnect through another exit |
| A virtual machine per account | In the guest system, below the browser | Before the browser starts | The guest's answers, in every realm | An image to rebuild and boot again |
| Separate hardware per account | Nowhere: the machine answers | The machine's answers, in every realm | Nothing to get wrong | |
| A browser with the engine itself changed | Inside the engine, in C++ | Before the first answer exists | The same answers as the document | A rebuild of hours, and a surface claimed but not built answers with the host's values |
What answering from inside costs
Depth is paid for in build time. A change inside the engine means compiling a browser for every platform, which is hours rather than a relaunch.
It is also paid for in bookkeeping. A build writes down which surfaces it actually carries by looking for each one in the source tree it just compiled.
The list is measured, not copied
Each surface is proven by a marker found in the tree at the minute of the build.
Silence means nothing is closed
A build that declares nothing is read as closing nothing, and the page covers everything.
The page steps back per surface
Whatever a build declares stops being corrected from the page, so two corrections never meet.
Where a shallow layer wins
Depth is not always the question being asked. Blocking a request never needed the page: a rule inside the network layer drops it with nothing visible to the page at all.
A browser you already have is a real advantage when the job is one account. The deep layer earns its cost when many accounts must stay apart on one machine.
What this comparison does not claim
- It does not claim that depth decides an outcome. An account is read by its behaviour and its history too, and no layer touches those.
- It does not describe any named product. These are ways of working, and what somebody else's build does is not ours to measure.
- Not every reading is answered inside the engine today. What a build does not declare is still corrected from the page, and such a correction leaves a replaced property where the engine leaves none.
- It does not isolate as deeply as a guest system. Profiles are processes on your own kernel and share it with each other and with you.
- The measurements come from our own build on one machine. Another machine gives other rows.
How to check this
Every statement above has a file behind it, and most have a stand that runs the code rather than describing it.
- The list of what a build closes is read next to the binary, and a missing one is read as nothing
- apps/desktop/src/lib/forkEngine.js
- One file decides what the page still covers, and a stand executes that decision
- apps/desktop/src/lib/дыры-страницы.js · apps/desktop/test/страница-отходит-когда-движок-умеет.js
- Each surface a build claims is proven by a marker found in the source tree
- engine/scripts/опись-умений.js · packages/shared/src/index.js · apps/desktop/test/engine-patches-real.js
- The document, a frame and a worker are read separately and compared
- apps/desktop/src/lib/fpAudit.js · apps/desktop/test/fingerprint-realms.js · engine/приёмка-отчёт.json
Questions
- An extension runs before the page's first script. Why is that not enough?
- Because the answer it corrects already exists. Wherever the correction did not reach, the original is still there, and two answers to one question say more than one odd answer.
- Why not move every reading into the engine at once?
- A build takes hours for each platform, so surfaces arrive in batches. Anything not in the current build is covered from the page until it is.
- How does the app know what a build closes?
- It reads a short list the build leaves next to the binary. A missing or damaged list is read as closing nothing, which is the safe way to be wrong.
- Can two corrections land on the same reading?
- No. One file decides what the page still covers, and a surface the build declares is dropped from that list.
- Does a replaced property show itself?
- The page level layer masks itself so a replaced function still reads as native code, and the self check asserts that. A value produced inside the engine has nothing to mask.
Read next
Agreement inside one fingerprint
The same eight ways sorted by whether the parts fit one machine.
The engine
What the built engine answers from inside, surface by surface.
Stealth plugin
Patching from inside the page, and where that ceiling is.
Worker realm
Why a background worker is asked separately from the document.
How a launch works
From the click to the first script, in order.
Find out which layer you are on
The check reads 12 values in your browser and sends nothing anywhere.