Tyche Labs · trusted-list observatory

The map of published trust

A trusted list is a state saying, in machine-readable form, whom it vouches for. Everyone knows the European one. Almost nobody has looked at the shape of the whole thing — who points at whom, which pointers answer a strict client, and whether anybody is obliged to check. This is that graph, fetched rather than described.

01

One hub, thirty-one lists

The European Union publishes a list of lists. Each member state, plus Iceland, Liechtenstein, Norway and an archived United Kingdom entry, publishes its own — naming the providers it supervises and the services they are trusted for.

Nothing here is drawn from a document we did not retrieve. Every circle is a file that answered.

31 machine-processable national lists, from one hub.
02

Forty-three pointers is not forty-three countries

The hub carries 43 pointers, and that is the number usually quoted. It is not a count of countries. 11 of them point at a human-readable PDF of a list that is already there in machine-processable form, and one points at the hub itself.

The small squares are those PDFs. They matter for the arithmetic: a fault in one list out of forty-three sounds like a rounding error, and the same fault out of thirty-one does not.

43 pointers = 31 lists + 11 PDF copies + 1 self-reference.
03

One of them has never answered

Ireland's trusted list is declared by the hub and cannot be retrieved by a strict client. The server sends one certificate where two are needed: the intermediate that links it to a trusted root is missing, so verification fails before the file is read.

The certificate does carry a pointer to the missing intermediate. A client willing to go and fetch it — a browser, and as it turns out a content-delivery network too — completes the chain and shows no problem at all. A client that only trusts what the server actually sent gets nothing. We asked from a second vantage point to be sure, and it answered there: the same endpoint, the same moment, two different verdicts.

Failed here in every one of 22 observations, and answered from the other vantage. The operator was notified before this page was published.
04

One is published without transport security at all

Slovakia's pointer is declared over plain http://, and answers there. The same host over HTTPS presents a certificate for a different name, so the encrypted path is the one that fails.

This is not the scandal it first looks like. The list carries its own XAdES signature, so its integrity does not depend on the transport. But a client configured to refuse plain HTTP — an increasingly ordinary policy — cannot fetch a national trusted list at all.

The list is signed. The channel is not. Those are different guarantees, and only one of them is present.
05

There is a second hub, and no edge between them

The Americas publish a regional list of lists in the same ETSI format, under the same standard, covering Argentina, Brazil, Paraguay and Uruguay. Chile appears too — not through the regional hub, but through Argentina's own national list.

Neither hub mentions the other. Not a broken link: no link. A client that knows how to read one has no path to the other, and nothing in either document suggests the other exists.

0 edges between the two hubs.
06

Four copies, three of them expired

The regional list is served from four addresses across three states. All four answer. All four carry a signature block. Three are byte-for-byte identical at sequence 7, whose declared next update passed 110 days ago; the fourth, in Brazil, is sequence 8 and current.

A signature proves who wrote a document. It does not say whether the document is still the one you should be reading. The only field that separates the current copy from the lapsed ones is the one no rule requires anybody to check.

Same standard, same signature check, 110 days apart.
07

And then the islands

Some states publish a trusted list that no hub points at. Switzerland, Ukraine, the United Kingdom's live list, Moldova, Serbia. They are reachable, current, and structurally invisible: you find them only if you already know the address.

Ukraine's was reissued the day before this measurement — the freshest list anywhere in the graph, and one nothing points at. Moldova's carries no provider section at all; its single pointer goes back to Brussels. Russia's exists and refuses us specifically, which from one vantage point we cannot distinguish from refusing everyone.

Serbia and Montenegro point at each other. Montenegro reaches the European hub only through Belgrade.
08

 

Every one of these lists is somebody's legal obligation to publish. Not one of them is anybody's obligation to check.

That is the finding. The defects are individually small and mostly easy to fix — a missing intermediate, a stale mirror, an unencrypted pointer. What is not small is that they persisted long enough for a first look to find them, in infrastructure whose entire purpose is to be relied upon.

The instrument

Explore the whole graph

Every node is a published artefact that this instrument fetched. Click one for what was measured about it, and for whether its territory is something the publisher declared or something we asserted.

Show

The numbers, and where each one comes from

30 of 31
European machine-processable lists that answer a strict client. Stated first because an instrument that only reports problems is campaigning, not measuring.
3 of 4
National pointers in the MERCOSUR regional list that answer. Paraguay's cannot be chain-verified — the same class of fault as Ireland's, in a different hemisphere.
1 of 4
Copies of the MERCOSUR list that are current. The other three are identical to each other and 110 days past their declared next update.
0
Edges between the two regional hubs. Europe and the Americas each publish a list of lists, and neither has ever heard of the other.

What this does not claim

It is not a security assessment

This measures whether a published endpoint answers a strict TLS client, and what each list says about its own currency. It is not signature validation, not supervision, not a legal determination, and not a vulnerability report. Nothing here is exploitable; several things here are simply not maintained.

Two vantage points, one moment

The series is measured from a single host in Estonia. Anything that fails there is asked once more from a second declared vantage on another network, because one host cannot tell “refuses everyone” from “refuses us”. Where the two disagree, the disagreement is the finding and both answers are published; we do not report the more convenient one. Two vantages are still not the world.

Labels are attributed

A node's territory comes from the list's own SchemeTerritory, or from the pointer that declares it. Ireland's list has never answered us; it is labelled IE because the European hub says so, not because we read it off a filename. Where we asserted a label ourselves, the panel says so.

Operators hear from us first

Where a named operator is involved we write to them before publishing, and a fix before publication is the outcome we would rather report. We do not route around a refusal. The second vantage identifies itself in its User-Agent, fetches only a fixed allowlist of the artefacts already measured here, and returns the observation rather than the document — it is an observation post, not a way to obtain something an operator has decided not to serve. A result gained by evading a block would not be a measurement of what a client sees.

Reproducing this

The instrument is three small programs and an append-only directory of dated runs. The classifier is declared in code before any percentage is computed, populations are never merged, and the page you are reading is generated from the run files rather than written by hand. Two defects the instrument found in itself — parallel workers manufacturing their own timeouts, and a namespace-blind parser misreading every prefixed list — are recorded in the README instead of quietly patched.

probe.pytransport: does the endpoint answer a strict client
freshness.pydeclared currency: issue date, next update, terminal lists
graph.pystructure: who declares a pointer to whom, followed transitively
export_web.pyassembles this page's data from the recorded runs