Chasing flipping bits
Bitsquatting has fascinated me for a while. Most of the published work looks at it from the outside: researchers register squatting domains or inspect DNS/query data and then study the traffic that shows up. I am more interested in the earlier question: why do these requests end up in the wrong place in the first place? We know it happens. The more interesting question is why.

Introduction
If the term is unfamiliar, bitsquatting is a variant of typosquatting. In a normal typo, a person types the wrong domain and ends up somewhere else. In bitsquatting, the idea is that a bit-level error somewhere in the chain changes one valid hostname into another valid hostname. A commonly cited example is microsoft.com turning into microsmft.com.
microsoft.com
|
| single-bit error somewhere in the chain
v
microsmft.com
Bitsquatting was introduced by Artem Dinaburg in 2011 and followed by Verisign’s 2012 study of checksum errors in DNS queries. Later work tracked bitsquat domain registrations and monetization, for example this, this, this and this
The important point for this post is that most of the literature measures the phenomenon indirectly. Researchers observe traffic arriving at bitsquat domains or examine DNS/query data, and from that try to infer where the corruption may have happened. Some of the research also highlight things such as cosmic rays, heat, or poor-quality memory flipping bits. Transit errors on long transmission lines are also flagged as possible source.
If we break down the possible sources of error, we end up with a fairly long list of things that all need to go right for the correct value to survive end to end. The list below focuses only on hardware and software sources of error and leaves human typing mistakes aside.
End-user equipment
- Keyboard errors, mechanical or electrical, or RF issues if using a wireless keyboard
- Computer hardware errors, for example in non-ECC RAM or the NIC
- User-space software, such as a browser
- Kernel-space software
- Consumer network equipment, both hardware and software
Transmission network
- Transmission lines and/or RF links
- Telco network equipment and their software
Server equipment
- Server hardware errors, such as memory or NIC faults
- User-space software, such as web servers
- Kernel-space software
Experiments
As the list of likely error sources and possible combinations is practically indefinite, I decided to run experiments instead and collect statistics. It would be impossible to test every combination directly, so I chose a few controlled setups and let them run for about a month each to see what happened.
Experiment 1
For experiment 1, I built a deterministic sender and receiver pair and ran them on two separate dedicated Hetzner servers so that every packet had to cross a real public Internet path and real carrier infrastructure rather than just a local switch or loopback interface.
The sender was a dedicated server in Hetzner’s Helsinki datacenter and the receiver was in Hetzner’s Falkenstein datacenter, roughly 1,500 km away.
+---------------------------+ +---------------------------+
| Hetzner Helsinki sender | --> | Hetzner Falkenstein recv |
| seq + CRC + HMAC + logs | | verify + logs + pcaps |
+---------------------------+ +---------------------------+
The sender transmitted fixed-size UDP packets at a constant rate. Each packet was generated deterministically from its sequence number and protected with redundant sequence information, a CRC, and an HMAC, so the receiver could reconstruct exactly what should have arrived and flag any corruption, duplication, or loss.
Alongside that, I also logged host telemetry and rolling packet captures on both sides so that if an anomaly ever appeared, there would be surrounding evidence from both the application layer and the network path.
Sender, Hetzner Helsinki:
- Intel Core i7-7700
- 64 GB non-ECC RAM
- Intel I219-LM NIC
Receiver, Hetzner Falkenstein:
- Intel Xeon E3-1275 v5
- 64 GB ECC RAM
- Intel I219-LM NIC
Experiment 2
For experiment 2, I used an old HP ProDesk 400 G4 and built a small controller-and-proxy setup that drove Chrome to repeatedly request a unique URL and then verified what URL the browser had actually requested.
The browser loaded a local control page which continuously generated fresh requests to unique hostnames to prevent caching. A local proxy recorded every observed request and checked it against the expected sequence so that any browser-side bit flip, corruption, duplication, or malformed request would be visible.
+-----------+ request unique URL +-------------+
| Chrome | -------------------------> | local proxy |
| control | | recorder |
+-----------+ <------------------------- +-------------+
| compare expected
| vs observed URL
v
anomaly or no anomaly
Test rig specs:
- HP ProDesk 400 G4
- Intel i5-7500
- 16 GB non-ECC RAM
Results
Experiment 1
Experiment 1 transmitted and received 25,045,601,117 packets over roughly one month, with an average rate of 9,998.18 packets per second against a target of 10,000 pps.
I did not observe any corrupted packets, duplicates, drops, or interface-level errors. For this specific setup, the reliability was remarkable.
Experiment 2
In Experiment 2, the browser loaded a webpage from a unique URL 11,184,322,926 times over roughly one month.
As in Experiment 1, I did not observe any bit flips or malformed requests, either from the browser or from the proxy used to capture the traffic.
The only interesting issue that did appear was unrelated to bitsquatting. Chrome, when repeatedly loading a single HTML page that continuously creates fresh Image() elements, caused the renderer to accumulate deleted shared-memory file descriptors until the tab eventually hung.
In my setup this happened deterministically at around 3,800 page loads, so I worked around it by closing and reopening a fresh tab after 3,000 loads to keep the experiment running.
Breakdown of the results
| Experiment | Setup | Events observed |
|---|---|---|
| Experiment 1 | Hetzner Helsinki -> Falkenstein, deterministic UDP, ~25.0B packets | 0 corrupt, 0 duplicate, 0 dropped, 0 errors |
| Experiment 2 | HP ProDesk, Chrome -> local proxy, ~11.9B requests | 0 malformed/corrupt requests, 1 unrelated Chrome renderer bug |
What can we infer from this?
Not as much as I had hoped. Absence of evidence is not evidence of absence.
These results apply only to the specific setups I tested, but they still say something useful. Across long-running experiments and very large numbers of events, I did not observe a single bit flip that survived high enough in the stack to become a meaningful application-layer error.
That matters because the original bitsquatting literature treats random bit errors in memory and related system components as a meaningful security concern, while other work has suggested that network-side DNS corruption is relatively rare.
My results do not disprove the earlier explanation, but they do suggest that in the environments I tested, the chain from “a bit flips somewhere” to “the browser or receiver accepts the wrong value and acts on it” is rarer than the surrounding indirect evidence might imply.
So the strongest claim I can make is not that bit flips never happen, but that I did not observe any bit flips that survived all the way up to a visible application-layer error in these two setups.
That still leaves the original question open in an interesting way. If human error does not explain every suspicious request, and if spontaneous higher-layer corruption appears to be this rare in practice, then the conditions that make bitsquatting observable may be narrower, more environment-specific, or more operational than the older literature suggests. If bitsquatting is real, under what exact conditions does it become observable?
Clearly, more experiments are needed. So with that, back to the drawing board.