On 13 August 2026, CISA published advisory ICSMA-26-225-01. An undocumented hard-coded credential, shared by every device unit, is authorized to bypass authentication. An attacker within Bluetooth range can arbitrarily manipulate stimulation parameters and state, and override safety limits. The affected products are the Flow Neuroscience FL-100 and Halo Neuroscience FL-100 transcranial direct current stimulation headsets, deployed worldwide. It is tracked as CVE-2026-18164, classed CWE-798, and was reported by the researcher A.C. Buglione. The vendor has shipped a firmware update through its companion app.
So the hole is closed, the researcher did the right thing, and the vendor responded. This is what the process working looks like, and it is a better teaching case than an open one.
What is worth your time is not the vulnerability. It is the question of which controls, in an ordinary development organization, would have stopped it before it shipped. The answer is that there are five, none of them exotic, and any one of them acting alone would have been enough.
Start with the impact, not the score
The CVSS v3.1 base score is 8.1, which is high but not the highest number you
will see this quarter. The vector is more informative than the score:
AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H.
Read the impact triplet. Confidentiality: none. Integrity: high. Availability: high. This is not a data breach. Nothing leaks. What an attacker gets is the ability to change what the device does, on a product that applies current to someone's head.
That is the whole argument for treating cybersecurity as a patient safety discipline rather than a privacy one, and it is why a finding like this deserves more attention than a 9-point confidentiality issue on a reporting service. The attack vector is adjacent rather than network, so it requires proximity. In a wearable that people use at home, proximity is not a meaningful obstacle.
Why the credential is there
Almost never malice, and almost never ignorance.
It is a factory provisioning path, or a service tool, or a debug interface that was supposed to come out before release. It works. It is invisible in normal use. Nothing in the build fails because of it. Somebody meant to come back to it.
I have done this. Not in a therapy device, but I have shipped a secret sitting in a config file because we were trying to get something out the door and standing up a proper key vault felt like a larger detour than it actually was. Every engineer who has shipped anything has a version of this story, and a teardown written by someone pretending otherwise is not worth reading.
The detail that turns an embarrassment into an advisory is shared by every device unit. A per-unit secret that leaks is one compromised device. A shared secret that leaks is the entire deployed fleet, all at once, with no revocation path that does not involve a firmware update reaching every unit in the world.
That distinction is the design failure. The credential is the bug. Drawing it is the job of the multi-patient harm view.
Five controls, any one of which was enough
Secret scanning in the pipeline. This is the one I would put first if you only ever do one, and it is the cheapest thing on the list. SonarQube and its peers detect this class, the platform-native scanners are free and already attached to your repository, and a coding assistant with the diff in front of it will flag a literal credential without being asked. Wire it into CI so it fails the build. That is what catches the specific case here, where the pipeline was probably already configured to inject secrets properly and somebody bypassed it once, under deadline, meaning to come back.
A threat model that asks about radio range. A structured threat model asks what an attacker within radio range can reach and what happens when one unit is compromised. Shared-credential scenarios fall out of that second question immediately, because the honest answer is "then all of them are." A threat model that enumerates assets and never enumerates adversary positions will not produce that.
Security requirements written as testable statements. "The device authenticates the companion app" is a principle. "Each unit derives a unique credential at provisioning, and no credential is valid across units" is a requirement with a test attached, and that test fails on the shipped build. This is the same conversion FDA keeps asking for in deficiency letters, and it is worth doing for engineering reasons long before it is worth doing for regulatory ones.
Penetration testing scoped to include the radio path. A test scoped to firmware and cloud misses this entirely. Not because the testers were weak, because the boundary they were given did not contain the attack. Scope decides outcome, which is exactly why the scoping stage carries as much weight as the test.
The architecture claim, audited against the shipped build. Somewhere in the design documentation there is a sentence describing how authentication works. The gap between that sentence and the binary is the entire story here. Reading security claims against the running system, and treating each one as something to be evidenced rather than restated, is the highest-value week available to most submission teams and it is almost never scheduled.
The failure is not any one of them
Every control on that list is ordinary. None requires a specialist, a budget line, or a tool you do not already have access to.
The failure is not that one was missing. It is that all five were, and that is a different kind of problem. Five independent controls do not go absent by coincidence. They go absent because nobody wrote down who owns which, and "we have security" turned out to mean five different people each assuming one of the other four was covering it.
That is the pattern worth taking from this advisory. Not "check for hard-coded credentials," which you already knew. Rather: for each of the five, can you name the person who owns it, and the artifact that proves it ran?
What is genuinely cheaper now
One thing has changed since the last time I wrote a secret into a config file.
The reason I skipped the key vault was never that I did not know better. It was that the setup was a detour with its own yak-shaving, at a moment when I was trying to finish something else. That calculation is different now. I have a model review changes before they go out, and it does not just flag the secret, it does the vault wiring, which was the actual thing I was avoiding. The excuse got substantially weaker.
That is not a replacement for the first control on the list. A check that depends on somebody remembering to ask for it is not a control, it is a habit, and the whole value of secret scanning in CI is that it runs whether anyone remembers or not. But it does mean the gap between knowing the right answer and doing the right answer has narrowed, which is worth something in exactly the moment these mistakes get made. There is more on where that tooling does and does not belong in a regulated codebase here.
If you want to check your own product
Run secret scanning across the repository and its history, because a credential removed from the current tree is still in the commit that removed it, and still valid if it was never rotated.
Then go looking specifically at provisioning, factory, and service paths, especially any that predate your current build pipeline. That is where these survive: not in the code anyone is actively editing, but in the parts that worked, were left alone, and stopped being read.
The part that worked
It is worth ending where the advisory ends rather than where the vulnerability does.
Somebody outside the company found this and had a route to report it. The manufacturer took the report, built a fix, and pushed it to deployed units through the companion app. CISA published once there was something users could actually do. Nobody learned about it from a conference talk.
That sequence is not luck and it is not free. It needs a published way in, a named person who owns what arrives, and a path from a fix out to units in the field, which is about a week of setup and one owner. The company that has it ends up with a closed advisory and a product that is better than it was. The company that does not has the same vulnerability, and eventually a researcher who ran out of patience.
This is engineering guidance, not legal or regulatory advice.