The Test Token That Shipped to Production
A developer test token shipped to production and worked as a master credential against a live diagnostics API. Here is how we found it and how to stop it.
The setup
The target was a medical-imaging diagnostics-AI company: the kind of product that ingests scans, runs detection models over them, and hands clinicians AI-generated findings. That places a dense concentration of sensitive material behind one API - patient imaging, diagnoses, and the detection metadata the models produce, which is itself clinical data.
We looked at this class of product because the value is concentrated and the surface is narrow. A diagnostics-AI company lives or dies on its API and its models, so the API is where the crown jewels sit. When the crown jewels sit behind one door, the only question that matters is whether the door’s lock is real.
Recon
Working black-box, from the open internet with no account, we mapped the production API and the client-side artifacts that talk to it. Modern web and mobile clients ship a surprising amount of their own logic, and that logic frequently names the endpoints, headers, and auth shapes the backend expects. We read those artifacts the way a new integrator would - looking for how the client authenticates and what it assumes the server will accept.
The hypothesis
Our working belief going in was mundane and reliable: left-in developer conveniences survive to production more often than anyone intends. Test accounts, debug flags, seed credentials, and backdoor tokens are added early to move fast, and the cleanup ticket to remove them competes with every feature deadline that comes after. It usually loses.
So the hypothesis was specific. Somewhere in this API’s history there was probably a shortcut - a way for a developer to authenticate without the full login flow - and there was a real chance it was still live. If it was, and if it carried the broad scope that test paths usually carry, it would not be a minor leak. It would be the whole authentication story.
What we tried
We looked for the shortcut in the places shortcuts hide: the auth-related constants and header handling in the client artifacts, the values the client fell back to, and the token shapes the API accepted. Among them was a token that did not look like a normal user session. It looked like something a developer would name for testing.
We tested it the most conservative way possible - a single request to a read-only endpoint, carrying that token in place of a normal credential. If the server rejected it, we would have learned nothing sensitive. It did not reject it. The token was live, valid against the production API, and it authenticated the request as a privileged caller. It was not a scoped test identity that could see a sandbox. It behaved as a master credential, bypassing normal authentication entirely.
What we deliberately did not do defines the rest of this. Once we had proven that the token granted privileged read and that a pivot toward connected storage existed, we stopped. We did not enumerate patients. We did not pull imaging in bulk. Proving the token was a master key does not require emptying the vault, and on clinical data the restraint is not optional.
What we found
One request, carrying the test token, authenticated as a privileged user and returned live production data:
-> GET /<diagnostics-read-endpoint>
Authorization: Bearer <hardcoded-test-token>
<- 200 OK
... patient counts, and imaging diagnoses with the
AI detection metadata attached ...
Behind that single credential sat patient counts and hundreds of thousands of imaging diagnoses, each carrying the AI detection metadata the product generates. The token was not scoped to a demo tenant or a synthetic dataset - it read real clinical records.
The blast radius did not stop at the API. The same privileged position pointed at a connected cloud storage bucket - the kind of object store where imaging files themselves are kept. We confirmed the pivot existed and was reachable from the position the token gave us, and we stopped there. The finding was already complete: one static token, shipped to production, was a master key to the diagnostic estate and a stepping stone to the underlying image store.
Why it happens
No one shipped this token on purpose. This is what “temporary” looks like when it outlives the sprint that created it.
A test or backdoor token gets added early because it makes development faster - one credential that exercises everything, no login dance, no per-environment setup. It is granted broad scope precisely so it can test broadly. Then the product ships, the token is meant to be pulled before production, and the removal competes with the next feature. Because it is invisible in normal use - real users never touch it, so nothing breaks and nothing flags it - it simply stays. The convenience that made it useful in development is exactly the privilege that makes it catastrophic in production.
For developers
If you build APIs, four controls close this:
- No static or backdoor tokens, ever. A credential that is not tied to a real, revocable identity has no safe place in your auth model. If you think you need one, you need a properly scoped service identity instead.
- Scan for hardcoded credentials in CI. Run secret-detection on every build and fail the pipeline when a token, key, or password is committed or bundled. The cheapest place to catch this is before it ships.
- Keep test auth paths out of production builds. If a test login shortcut must exist, gate it behind a build flag that is off in production, so the code that honors it is not even present in the shipped artifact.
- Scope test identities to nothing. Any account or token used for testing should have the narrowest possible access, so that a leaked one is worthless. The failure here was not only that the token shipped - it was that it carried master scope.
And one detection step: audit your production auth logs for a credential that authenticates as privileged but never rotates and never expires. A token that has been valid, unchanged, since launch is worth investigating.
The takeaway
A test token is a loaded gun left on the workbench. It is added for the best reasons - speed, convenience, coverage - and it is dangerous for exactly those reasons, because the broad scope that made it useful is the scope an attacker inherits the moment it ships. The fix is not a better token. It is refusing to carry static credentials at all, catching them before they ship, and making sure anything test-shaped is scoped to nothing.
This teardown is one instance of a pattern we see repeatedly. We wrote up the general case, and how to defend against it, in When New Accounts Are Born as Admin.
Frequently asked
What is a hardcoded credential vulnerability?
How does a test token become an auth bypass?
How do you prevent hardcoded credentials from reaching production?
This is one finding from a harness that runs continuously. See how Greywatch finds, proves, and fixes them.
How it works →

