We Found a Stable Firefox Identifier Linking All Your Private Tor Identities
51 points by knl
51 points by knl
Fixed in Firefox 150 and ESR 140.10.0 (both released on 2026-04-21), but will affect all Firefox-based browsers.
Huh, hash-ordering as fingerprinting is clever. I bet this appears elsewhere.
Tangentially related is reproducible builds, which wants build processes to produce bit-for-bit deterministic build artifacts ("the same fingerprint").
https://reproducible-builds.org/docs/stable-outputs/ documents methods to configure hash libraries to have stable order.
Oh it sounds like it’s not persistent, but I’m surprised it shared across tabs (it sounds like all tabs end up talking to the browser process for indexeddb access).
Sorting is an absolutely sensible way to deal with this given the constraint of a shared interface (if the interface wasn’t shared a random seed would be sufficient).
JS resolves this separately by having specified deterministic iteration ordering :D
I must be missing something, but why is it not just as valid for an origin to create databases with a specific patterned name to use as an identifier? Obviously, this seems like an obvious thing Tor would protect against, but sorting doesn’t protect anything if there’s a unique id in the list.
Yeah, it would be nice if there was more information about the actual bug.
What I think is happening is something like:
Because the UUIDs are created from a key that is common to all processes then when multiple completely independent tabs create a set of the same DB names -- something as simple as {"1", "2", "3",...} -- they will all get the same UUIDs, and as result when inserted into the hash table the collisions will be the same, so then an attacker can use the enumeration order as a unique identifier.
This is very much what i think is happening based on the details that are available.
Using a different value for (1) for every page load would be effective, but in general the most robust privacy protection for this kind of attack is deterministic ordering: because it also means an attacker can't leak information by inducing collisions with other pages, etc.
I bet this was originally deployed as a security feature: adding entropy during UUID creation to avoid hash-collision attacks.
yeah, and to an extent it does - it could also prevent sites from relying on ordering. The other extreme is something like JS insertion order guarantees, which is its own pain, but is a much more robust privacy protection (though to be very clear this decision was the combination of defense against hyrum's law and compatibility with existing insertion order semantics).
The fault lies in having a shared secret for all these tables (uuid generation, hashing, or whatever it was). Because the whole point of this kind of randomization is that you cannot ever reuse it.
No doubt. I did the same thing in my hash tables for that exact reason. Mine are insertion-ordered though.
I went and reread. Yes. I missed something fierce.
TBF it is not the mostly clearly written article.
I had to re-read it to answer your question, then go and look at the code they pointed to, and finally when even that wasn't sufficient spend some time trying to think about how I would try to implement the attack they're talking about, and then work back to what the implementation was probably doing.
:D