Onionspector - now let's see what the onion knows about you

· 0ut3r Space ·

14 min read Original article ↗

A few days ago I built Onionservatory, because apparently Onion Services also deserve to be judged by automated security tools.

It answers questions like:

1
2
3
4
5
6
Is this Onion Service configured properly?
Does it leak resources to the clearnet?
Are the security headers sane?
Does it depend on external JavaScript?
Where do its forms submit?
Is it reasonably fast for Tor?

Useful.

But after staring at the service side for long enough, another question appeared:

Fine. We know what the Onion Service is doing. What does the Onion Service know about us?

So naturally, instead of closing the terminal and doing something productive, I built another tool.

It is called Onionspector.

onionspector

The other side of the connection

When you visit a website, the server does not just receive:

1
GET /

and politely mind its own business. Even without JavaScript, an HTTP request can reveal quite a lot about the browser making it.

Things such as:

1
2
3
4
5
6
7
8
9
User-Agent
Accept-Language
DNT
Global Privacy Control
Referer
Fetch Metadata
Client Hints
cookies
HTTP version

may already tell the service something about your browser configuration. Enable JavaScript and the list gets significantly more interesting.

Now a page may inspect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
screen dimensions
viewport
timezone
locale
CPU concurrency
device memory
touch support
Canvas
WebGL
fonts
AudioContext
storage APIs
media APIs
browser features

None of these values necessarily identifies you by itself. That is not how browser fingerprinting usually becomes interesting.

The problem is the combination.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
browser
+
screen
+
timezone
+
fonts
+
GPU
+
Canvas
+
AudioContext
+
a dozen small browser quirks

and suddenly “just another visitor” may start looking rather less generic. Tor Browser spends a considerable amount of effort trying to prevent exactly that. Onionspector lets you see how well that effort is working from the perspective of an Onion Service.

Correlation is where it gets interesting

A single fingerprinting signal is usually not very exciting. Your timezone alone does not identify you. Neither does your screen size, Canvas behaviour, WebGL renderer or browser language. But if the same unusual combination starts appearing across several Onion Services, things become more interesting. Imagine one operator controls multiple sites in the Tor network and quietly collects browser-visible metadata from all of them. They may start seeing something like:

1
2
3
4
5
6
same unusual viewport
same timezone
same WebGL behaviour
same font exposure
same Canvas characteristics
same browser quirks

on:

1
2
3
4
market A
forum B
service C
directory D

Individually, those signals may mean very little. Together, they may provide enough similarity to suggest:

This could be the same browser visiting all of these places.

Now add accounts. Maybe you register as random_darknet_username on one service, use the same or related identity somewhere else, log in repeatedly from a browser exposing a similar fingerprint and keep following the same browsing patterns. Suddenly the operator may not know who you are in the real world, but they may be able to build a reasonably useful picture of your anonymous identity:

1
2
3
4
5
where you appear
when you appear
which services you visit
which accounts may belong together
how your browser behaves

That is correlation. And correlation is often much more useful than discovering one magical value that says:

1
HELLO, MY NAME IS BOB AND THIS IS MY HOME ADDRESS

Large advertising and analytics companies have used variations of this idea for years on the clearnet: combine identifiers, browser characteristics, behaviour and metadata across many places to build increasingly detailed user profiles. Usually this is explained with words like:

1
2
3
4
personalization
analytics
engagement
advertising

which sounds much nicer than:

1
we watched you move around the Internet and took notes

The Tor network changes the transport and removes many conventional tracking opportunities, but browser-visible metadata can still matter if enough of it is exposed and somebody controls enough observation points. So the real question is not only:

Can this one Onion Service identify me?

A better question is:

If several services can observe the same unusual browser characteristics, how easily could those observations be correlated?

That is one of the reasons Tor Browser tries so hard to make users look alike. The boring browser is the useful browser. Somewhere, Mark Zuckerberg is probably still trying to understand why humans dislike being tracked. Give him time.

One button

I deliberately did not turn this into:

1
2
3
4
5
6
Passive mode
Advanced mode
Expert mode
Ultra fingerprint mode
Danger mode
Click here if you enjoy settings

There is one test. You open Onionspector and get:

1
2
3
4
5
6
Inspect your Tor Browser.

Check what your browser reveals to Onion Services and
how exposed its fingerprint is.

[Test my browser]

Nothing happens before you click it. Once you do, Onionspector performs every check that your current browser configuration permits. First, the server-visible checks run. Then, if JavaScript is available, browser-side fingerprint checks continue automatically. If JavaScript is disabled, the test simply stops where JavaScript becomes necessary and tells you which additional checks could not be performed. No second test. No hidden “advanced” button. No requirement to enable JavaScript just to see the basic result.

What can be checked without JavaScript?

Quite a bit. The first stage uses only the HTTP request that reaches Onionspector. It looks at signals including:

1
2
3
4
5
6
7
8
9
10
11
12
User-Agent
browser family
Tor Browser-like profile
Accept-Language
Client Hints
Referer
Fetch Metadata
Global Privacy Control
Do Not Track
Cookie header
HTTP version
Onion Service context

This is useful because disabling JavaScript does not make the browser completely invisible. The server still has to receive an HTTP request. And HTTP requests have headers. Technology remains annoyingly functional. For example, a browser might send something roughly resembling:

1
Mozilla/5.0 (...) Gecko/20100101 Firefox/140.0

That is useful information. But Onionspector intentionally does not say:

1
2
3
THIS IS DEFINITELY TOR BROWSER
100% CONFIRMED
VERY SCIENTIFIC

because that would be nonsense. A normal Firefox instance can imitate some Tor Browser-visible properties. Privacy extensions can modify others. Custom configurations can produce strange combinations. So the result is deliberately expressed as something like:

1
2
Tor Browser-like
Medium confidence

rather than pretending that an HTTP header is a cryptographic attestation of your browser installation.

Then JavaScript arrives

If JavaScript is allowed, Onionspector automatically continues with browser-side tests. This is where fingerprinting becomes much more interesting. The current checks include:

1
2
3
4
5
6
7
8
9
10
11
navigator.userAgent
navigator.platform
navigator.languages
navigator.vendor
User-Agent Client Hints
webdriver
GPC
DNT
cookieEnabled
plugins
MIME types

then window and display information:

1
2
3
4
5
6
7
viewport size
outer window size
screen size
available screen size
devicePixelRatio
colorDepth
letterboxing indication

then environment information:

1
2
3
4
5
6
timezone
locale
hardwareConcurrency
deviceMemory
touch capabilities
Network Information API

and finally some of the usual fingerprinting favourites:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Canvas
WebGL
WebGL vendor
WebGL renderer
fonts
AudioContext
WebRTC API presence
mediaDevices
WebGPU API
CSS media queries
localStorage
sessionStorage
IndexedDB
Service Worker

Basically, a collection of things a normal site could inspect if you let it execute JavaScript. Which is exactly the point.

Letterboxing

Screen dimensions are one of the obvious browser fingerprinting signals. If everybody exposes their exact window size:

1
1537 x 947

that can become another useful attribute in a fingerprint. Tor Browser uses letterboxing to push users into standardized window-size buckets rather than exposing endlessly varying dimensions. Onionspector looks at the viewport and reports whether the dimensions resemble those expected buckets. That does not prove your browser is perfectly protected. But it gives you a useful indication of whether one of Tor Browser’s most visible anti-fingerprinting mechanisms appears to be doing its job. It may also remind you why maximizing a privacy browser window just because you paid for the entire monitor is not always the most anonymous lifestyle choice.

Canvas

Canvas fingerprinting is one of the classics. JavaScript draws something into an HTML canvas and reads the resulting pixels.

Differences in:

1
2
3
4
5
6
operating system
GPU
graphics stack
drivers
font rendering
browser implementation

can influence the result.

So instead of asking:

What GPU do you have?

a site can sometimes ask your browser to draw something and let the pixels answer indirectly. Elegant. Slightly horrifying. Very web. Onionspector performs a local Canvas probe and reports what the browser allows it to observe. It is not trying to build a global fingerprint database. There is no server-side collection of Canvas hashes. The result stays in the browser.

WebGL

WebGL is another useful source of fingerprinting information. Depending on browser protections, JavaScript may be able to learn details about the rendering environment, including vendor and renderer information. That can expose surprisingly specific values on normal browsers. Onionspector checks:

1
2
3
WebGL availability
vendor
renderer

and shows what is actually visible.

Again, the interesting question is not:

Does WebGL exist?

The more useful question is:

How specific is the information my browser is willing to expose?

A privacy browser saying something generic is rather different from a normal browser cheerfully introducing your GPU by full name.

Fonts

Installed fonts are another classic fingerprinting signal. A very unusual collection of fonts can reveal information about:

1
2
3
4
5
operating system
installed software
language
profession
user customization

and probably the fact that at some point you downloaded thirty-seven cyberpunk fonts and used exactly one of them. Tor Browser attempts to reduce font-based uniqueness. Onionspector performs a small local font sample to see what the browser allows the page to distinguish. It deliberately does not try to enumerate thousands of fonts. The idea is to inspect the protection, not recreate a 2014 advertising SDK.

AudioContext

Yes, audio can also be used for browser fingerprinting. No, the browser does not need to play death metal through your speakers. AudioContext can process an audio graph internally and numerical differences in the resulting signal can become another fingerprinting attribute. Onionspector performs a small local AudioContext probe when the API is available.

Again:

1
2
3
nothing is uploaded
nothing is compared against a global database
nothing is played

It simply shows that this class of signal is available to the page.

WebRTC

WebRTC deserves special clarification because people understandably associate it with IP leaks. Onionspector does not perform an active WebRTC leak test. It does not:

1
2
3
4
5
create a peer connection
contact a STUN server
collect ICE candidates
open a WebSocket
contact a clearnet endpoint

It only checks whether relevant WebRTC and media APIs are exposed to JavaScript. That is intentional.

I wanted a browser inspector, not a service that says:

Let me test whether you leak data by first contacting six unrelated servers.

Privacy engineering can become remarkably creative when left unsupervised.

No fingerprint submission

This is probably the most important implementation detail. The JavaScript-only results are not submitted to the server.

There is no:

1
POST /fingerprint

There is no fingerprint database. There is no account. There is no user history. There is no:

1
2
Congratulations!
You are visitor #473829 and we have seen you before.

The advanced fingerprinting code executes locally and renders its results locally. The Content-Security-Policy for the test page also includes:

1
connect-src 'none'

so the script itself cannot start using:

1
2
3
4
fetch()
XMLHttpRequest
WebSocket
sendBeacon()

to quietly send its findings somewhere else. A fingerprint privacy checker silently uploading your fingerprint would be a reasonably good joke. I just did not want to make it.

JavaScript disabled?

That is fine. If JavaScript is blocked, Onionspector still completes all server-visible checks. Then it tells you something along the lines of:

1
2
3
4
5
6
7
8
9
Additional checks unavailable.

JavaScript is blocked, so JavaScript-only fingerprint
signals could not be inspected.

The server-visible checks above are complete.

Allow JavaScript for this Onion Service and run the
test again if you want the additional local checks.

That behaviour is important. Disabled JavaScript is not treated as:

1
2
3
ERROR
TEST FAILED
PLEASE LOWER YOUR SECURITY SETTINGS

It means exactly what it means: Onionspector cannot observe JavaScript-only information because your browser did not permit JavaScript to observe it. Which, when testing browser privacy, is itself fairly useful information.

The Tor Browser reference

There is another problem with browser checkers. Browsers change. Tor Browser changes. Firefox ESR changes. A privacy test hardcoded against today’s browser profile eventually becomes tomorrow’s confidently incorrect browser profile. At the time I built the first version, the validated reference was:

1
2
Tor Browser 15.0.x
Firefox ESR 140

That reference will not remain current forever. So Onionspector has a small server-side reference checker. Once a week it asks the official Tor Browser release endpoint for the current stable release. The request itself is sent through Tor. At the time of writing it reports:

1
Tor Browser stable: 15.0.21

The important part is what happens when this changes. Onionspector does not automatically rewrite its fingerprint heuristics. If Tor Browser eventually moves to another major profile, the reference becomes:

1
Profile review required

instead of blindly assuming that changing:

1
140

to:

1
whatever-new-number

is enough to understand a new browser release. Automation is useful. Automating incorrect assumptions is also useful, mainly if you enjoy debugging false positives.

Can it tell me that my Tor Browser is outdated?

Sometimes. But not with magical precision. Tor Browser deliberately normalizes browser-visible information. A website cannot necessarily distinguish:

1
Tor Browser 15.0.20

from:

1
Tor Browser 15.0.21

just by looking at the exposed browser fingerprint. And that is a feature.

What Onionspector can detect more reasonably is a profile that appears substantially older than the current reference.

For example:

1
2
3
4
5
Current reference:
Firefox ESR 140

Observed Tor Browser-like profile:
Firefox ESR 128

may produce:

1
2
3
4
WARN
Tor Browser version freshness

Possibly outdated

But if both releases expose the same ESR major, Onionspector does not pretend it knows the exact patch version. A privacy test should probably avoid defeating privacy protections just so it can print a more impressive version number.

What does a good result look like?

That is slightly different from Onionservatory. There is no:

1
A+

and I deliberately like it that way. Onionservatory evaluates a service configuration, where scoring makes sense. Onionspector is looking at a collection of browser-visible signals.

The goal is not:

1
Privacy: 97/100

because that number would mostly create an exciting illusion of mathematical certainty. Instead, the result tells you what is exposed, what appears standardized, what differs from the current Tor Browser-like profile, and which checks were unavailable.

You then get something much more useful:

1
2
3
4
5
6
7
8
Tor Browser-like profile
User-Agent standardized
letterboxing indication present
timezone standardized
Canvas protected
WebGL information limited
font exposure limited
JavaScript-only checks completed

or perhaps:

1
2
3
4
5
browser profile differs
screen dimensions unusual
timezone exposed
WebGL renderer specific
additional hardware information available

That tells you why something is interesting. Not just that an algorithm deducted seven privacy points because a spreadsheet said so.

It is not a deanonymization oracle

Another important distinction. Onionspector cannot tell you:

1
YOU ARE ANONYMOUS

It also cannot tell you:

1
YOU HAVE BEEN DEANONYMIZED

Browser fingerprinting is one component of privacy. There are many others:

1
2
3
4
5
6
7
8
9
10
11
network behaviour
account reuse
cookies
authentication
application identifiers
typing behaviour
operational security
browser modifications
downloaded documents
external applications
human decisions

A perfect-looking browser fingerprint does not save somebody who logs into the same personal account from Tor and the clearnet. Technology unfortunately still refuses to patch humans automatically.

Onionspector answers a much narrower question:

What browser-visible information can this Onion Service see right now?

That is enough.

Why another Onion Service?

Just like Onionservatory, Onionspector is onion-only. The service is specifically about Tor Browser privacy. Its intended users are already using Tor Browser. So the architecture is deliberately boring:

1
2
3
4
5
6
7
8
9
10
11
Tor Browser
|
v
Onionspector Onion Service
|
v
Nginx + PHP
|
+--> server-visible checks
|
+--> local browser checks if JavaScript is allowed

There is also a tiny scheduled reference updater:

1
2
3
4
5
6
7
systemd timer
|
v
Tor SOCKS
|
v
official Tor Browser release reference
  • No database.

  • No accounts.

  • No analytics.

  • No fingerprint collection infrastructure.

  • No container orchestra slowly achieving consciousness.

It is a small tool. I would like it to remain one.

Onionservatory + Onionspector

The two projects now look at opposite ends of the same connection.

Onionservatory asks:

1
What is this Onion Service exposing?

Onionspector asks:

1
What am I exposing to this Onion Service?

Together they cover a surprisingly useful part of the interaction:

1
2
3
4
5
6
7
8
9
                 Tor connection

Browser ------------------------------> Onion Service
| |
| |
Onionspector Onionservatory
| |
v v
What can the site see? What is the site doing?

One looks inward. One looks outward. Neither launches nmap. I consider that personal growth.

Use it

Open Onionspector in Tor Browser and press:

1
Test my browser

Try it with your normal Tor Browser configuration. Then try different Tor Browser security levels. If you are curious, compare it with ordinary Firefox or Chromium routed through Tor and see how different the browser-visible surface becomes. Do not interpret every difference as an immediate vulnerability. The interesting part is understanding what a website can observe and which signals Tor Browser attempts to standardize or restrict. And if Onionspector tells you that your beautifully customized privacy browser exposes a unique combination of screen size, timezone, GPU, fonts and twenty APIs… well. At least the wallpaper is probably nice. I am interested in strange results, browser configurations, Tor Browser updates, false positives and fingerprinting edge cases that make the assumptions fall apart. That is usually where these tools become useful.

Oh, and here is the Onionspector URL:

1
http://wcxzuepn4llq33dxino5iy3hwppjjpcrt5lvvydv6pvgnnobuyjoxmid.onion/