This is the third time I have written about transit, and the pattern has held each time. The first was OMNY's account portal, where the fare rails were fine and the soft account layer around them was not. The second was the phone, where the Secure Element holds and the trust built around it is what cracks. This one moves to the quietest layer of all, the data the agency hands out on purpose, and the pattern holds a third time. The protection is real. The thing next to it is the exposure.
The MTA publishes a dataset called the Subway Origin-Destination Ridership Estimate, available right now on data.ny.gov, one file per year from 2021 forward. It is a genuinely good civic release. For every populated origin-destination pair it gives an estimated rider count, broken out by month, day of week, and hour of day, with the station complexes and their approximate coordinates. Planners use it. Researchers use it. It carries no names and no card numbers, which is exactly why everyone involved can call it anonymized and mean it.
The counts are the problem.
Small cells, real names
A rider's trip is hidden only among the other people who made the same trip in the same time bucket. That hiding group is the rider count, and the count is published. When a given origin, destination, and hour has four hundred riders, the individual is genuinely lost in the crowd. When it has three, the crowd is three people. When it has one, there is no crowd at all. The file is telling you that in a typical such hour, exactly one person makes that trip, and it is telling everyone who downloads it.
This is not a hunch. De Montjoye and colleagues measured it in "Unique in the Crowd: The privacy bounds of human mobility" in 2013, and the number has aged well: four approximate time-and-place points single out about ninety-five percent of people in a mobility dataset. A small origin-destination-hour cell is one of those points, published in advance. An attacker breaks no encryption and touches no turnstile. They read the open file and wait for a single anchor, one social post with a location, one photo timestamp, one observed entry, to collapse a small group to a single person and attach a name to a routine.
The MTA's release is aggregated across days within a month, so the granularity is "a typical Tuesday at eight," not "this exact Tuesday," which softens the one-off trip and does nothing for the commuter whose whole value as a target is that the trip repeats. Routine is what re-identification feeds on, and a commute is routine by definition.
The auditor, and what it found
I did not want to describe this in the abstract, so I built the defender's version of it and ran it. It is public and it is called five_riders_of_the_storm. It reads a ridership-style release, measures every published cell against a k-anonymity threshold, and reports how much of the file re-identifies the rider. The data it runs on is synthetic and generated in place, shaped like the real schema. No actual rider, dataset, or agency is touched.
On a release of 389 trip cells, the audit flagged 141 of them, more than a third, sitting in a group of fewer than five riders. Sixty-one of those were a group of one. Scrubbing the names changed nothing, because the name was never the identifier. The count was.
as published: cells= 389 k<5 cells= 141 (36.2%) unique= 61 min_k=1
The fixes, and what they cost
The good news is that the fixes are old and well understood, and the audit measures each one instead of asserting it.