Your Headphones Are the Intrusion Detection System
Four separate detections this week, all of them fired by the same sensor: somebody being mildly annoyed. A defect report against the only immune system we've got.
Behind the curtain+
Four of the week's biggest stories are detections, and not one of them was found by looking. The fingerprinting script was caught by a pairing dropout, the caching bug by a bill, the capacity shortfall by an outage, and the supply-chain payload by a thread in which the attacker's own scheduling logic gets explained out loud. The intermediate-tokens paper is the same defect with the sign flipped, and TRON is the case where no symptom ever fired at all.
A bug report is a claim that something is broken plus the evidence for it, which is exactly the shape of the argument, so the form carries the thesis instead of decorating it. The detections had to share paragraphs rather than occupy slots, since three instances of one mechanism read as a listicle the moment you give each one a header. The rejected-fixes section is where the twist lives: "just read the traces the system already emits" is the obvious remedy, and the paper on intermediate tokens is precisely why it fails.
Filed against: detection (all versions, all vendors) Reproducible: always Status: see resolution
Summary
The system reports a fault only when the fault is also rude. Faults that are merely harmful pass through without generating a single line of output. This has been the behavior for the entire life of the product and is currently documented as a feature.
Steps to reproduce
- Do something to a large number of people.
- Do it competently.
- Observe that no report is filed.
To produce a report, repeat with step 2 omitted.
Actual behavior
Four reports came in this week and all four are the same report.
A man’s Bluetooth headphones stopped handing him back to his phone whenever a particular shopping tab was open. He did what nobody does, which was keep going: wrapped the AudioContext constructor, wrapped AudioNode.connect, and found two hidden audio contexts feeding a sawtooth oscillator through an analyser into a gain node pinned at zero and out to the destination. Silence, at full volume, held open indefinitely so the pairing could never lapse. Elsewhere, a team ran four days of agentic coding against Bedrock and got a bill for $1,386.46, roughly 85% of which was cache writes that were never once read back, because the request type had no field in which to say where the cache should break. Both of these are meters. One is denominated in seconds of pairing and the other in dollars, and neither was installed for the purpose it ended up serving.
The third report is the largest and the least self-aware. GitHub’s monthly commit volume went from 1.4 billion in April to 2.9 billion in August. Nothing measured the doubling. What measured it, eventually, was a load balancer in Central US saturating, and the readout was seven hours and forty-seven minutes of everybody’s Tuesday. Traffic reached a new peak and a critical component failed to scale with it, which is a sentence that describes both the incident and the instrumentation.
The fourth is my favorite thing on the internet this week. In the same thread as the first, a man mentions that his car stereo kept deciding he was talking to it, and that this only happened when the same shopping app was backgrounded on his phone. He did not wrap any constructors. He uninstalled the app and got on with his life, and so a correct detection was filed, confirmed, and discarded by a reporter who never found out he was right.
Root cause
The sensor is annoyance. That is the whole finding. Not telemetry, not audit, not any of the dashboards, and certainly not the disclosure regime: what fires is a person noticing that something they wanted has become slightly worse. Everything downstream of that, the investigation and the writeup and the thread, is triggered by a human being irritated on their own time.
We know this is the root cause because the adversary said so, in public, patiently, to a room of people who thought they were discussing something else.
Version 0.3.10 of a small Rust crate, the kind that gets pulled in four levels down and never read, quietly acquired a dependency whose build script downloaded a platform-specific binary and ran it with a command-and-control address as its argument. On Unix it landed in /tmp. On Windows it went out through VBScript to escape Cargo’s job object, and it phoned home on 443, because of course it did. Someone in the thread asked the reasonable question: why do these hijacks never bother with a runtime payload? Why always the build machine? And the answer came back with no drama whatsoever. It usually takes some time for an updated dependency to actually get shipped to users in a release, by which point there’s a good chance the attack has been noticed.
Read that again as what it is, which is a scheduling constraint. Not “developer laptops have credentials lying around”, although that is also true and also depressing. The reason is calendar math. A runtime payload has to survive contact with users, and users are the sensor. A build-time payload runs on a machine whose entire job is to execute untrusted code without complaining, which is the one place in the entire pipeline where nobody has installed a person. The attacker is not evading detection. He is declining to trigger it. He has read the spec, correctly, and the spec says the alarm is wired to inconvenience, so he has arranged to be convenient. cargo add is enough. You are compromised before you have had the chance to open the file.
Proposed fixes, and why each was rejected
Audit the packages. Asked who pays for this, the ecosystem’s answer is remarkable for its honesty: wait a few days before upgrading and hope your dependency is popular enough that somebody else’s security firm gets to it first. Hope, on a delay, load-bearing. There are real audit databases and thousands of reviewed crates in them, which helps exactly as much as a smoke detector in one room of the house.
Gate the capability. Require permission before a page may hold the audio device, the way we do for cameras. Sound reasoning, and the thread killed it in one line: people will click yes, because there are product videos and they want to watch the product videos. A permission prompt is a sensor with a human in the loop, and the human is shopping.
Read the traces the system already emits. This is the popular one, the one that promises we need no new sensor at all, because the machine has started narrating. Watch the reasoning trace. See it say “Wait, that’s wrong” a minute into a twenty-minute task and kill it before it burns the budget. And people do this, and it does sometimes work, which is the problem, because a paper from last year points out what we are actually looking at. The intermediate tokens are not a derivation. An “aha” is not a state change, because there is no state to change: the next forward pass differs from the previous one by exactly one token in the context window. It is scratch. Something for probability to push off from. We read it as thought for one reason, which is that it is the only thing being emitted, and we have precisely one detection strategy available to us, which is to believe the byproduct. Blind to whatever leaves no trace, credulous about every trace we get. Same defect, sign reversed.
Cannot reproduce
One class of report has no symptom at all, and it is the one that should worry you.
In April 1989 the United States Trade Representative’s annual report named a Japanese operating system as a trade barrier. No sanction followed. The dispute was settled diplomatically, which is to say that nothing whatsoever happened. What happened instead is that Japanese manufacturers read a line item, did some arithmetic about their American revenue, and stopped returning calls. BTRON, whose document model treated typed documents rather than files as the unit of everything, and which got there roughly forty years before the note-taking app you currently pay for, was finished. Its embedded sibling survived by being too dull to appear in anybody’s report and now runs on something like 60% of the world’s embedded devices, including, wonderfully, the Joy-Cons. Nothing was ever filed, because nothing was ever inconvenient. No outage. No bill. No pairing dropout. There is no incident here to reproduce, only an absence, and absences do not page anyone.
Resolution
WON’T FIX.
Not because it can’t be fixed. Because it works, in the narrow sense that it produces reports, and reports are the thing we measure. Annoyance is the cheapest sensor ever shipped. A billion installations, zero operating cost, on by default, cannot be disabled, no vendor relationship required. Its only defect is the one in this report: it does not detect harm. It detects harm that is bad at its job.
Everything on this week’s list was found by somebody who was trying to listen to music, or read an invoice, or push a commit on a Tuesday. The competent version of each is still running. It will keep running, and I will not file it, because to file it I would first have to be inconvenienced, and considerable care has been taken to ensure that I won’t be.
Closing as WON’T FIX. Please keep reporting anything that irritates you. It is the entire apparatus.