Five Ways a Healthcare App Leaks PHI Without Anyone Noticing
A healthcare application can pass a demo perfectly and still be leaking protected health information in four or five places at once. That is not a criticism of the people who built it. The leaks all live in the plumbing, in logging and error handling and deployment config, which is exactly the layer that gets deferred when the goal is to prove the idea works. The interface is the part everyone looks at, and the interface is almost never where the problem is.
What follows are the shapes that keep recurring. Every example below is invented, with fake patients, fake file paths, and fake keys, but the patterns are the ordinary consequences of building something quickly rather than anything exotic.
1. The application logs
This is the most common one by a wide margin, and it usually starts as a single debugging line that nobody removed. Almost nobody decides to log patient data, which is part of why it survives so long.
INFO summarize_request patient="Maria Alvarez" dob="1982-03-14" mrn="4417-8823"
Logging the whole request is the fastest way to work out why something failed, so it goes in early and then quietly survives into production. The reason it matters more than it looks is that logs travel. They get shipped to an aggregator, retained for thirty or ninety days, indexed for search, and made readable by anyone with dashboard access, which is usually a wider group than the people who can query the database. Whatever careful story you have about encryption at rest for your patient records, the logs are almost certainly outside it.
The fix is to redact at the logging boundary rather than at each call site. Filtering in a formatter or a middleware layer means a new endpoint written next month inherits the protection instead of needing someone to remember.
2. The call to the model provider
If the feature summarises notes or answers questions about a chart, then raw clinical text is going to a hosted model, and that is not incidental. It is the entire point of the feature.
resp = provider.completions.create(
messages=[{"content": raw_note_text}])
The question is not whether the text leaves, because it has to. The question is what covers it on the way out. Some providers will sign a business associate agreement and some will not, and the ones that will often cover only specific services or tiers rather than the whole platform. A zero-retention setting is a useful control but it is not a BAA, and the two get conflated constantly.
Where a BAA is not available, or does not cover the path you are actually using, the alternative is to strip the identifiers before the request leaves your boundary. That is what Philter AI Proxy is for, sitting between the application and the provider so the clinical context survives and the patient identifiers do not.
3. The crash reporter
Error monitoring is the leak people are most surprised by, because nobody chose it. The default configuration of most error reporting SDKs captures a great deal of context to make debugging easier, and that context can include request bodies, local variables, and breadcrumb trails of recent activity.
When a summarisation call throws, the local scope holding the note text is exactly the sort of thing that gets serialised and sent to a third party. It arrives there with none of the access controls the application applies, and it lands in a vendor account that probably was not part of anyone’s compliance review, because it was added in an afternoon to fix a bug.
Most of these SDKs support scrubbing hooks that run before an event is transmitted. They are worth configuring deliberately rather than trusting the defaults, and the vendor is worth adding to the list of places patient data can reach.
4. Git history
Removing a key in a later commit does not remove it from the repository. It sits in history, and anyone who clones the repo gets it.
config/settings.py AWS_ACCESS_KEY_ID = "AKIA****************"
This is a PHI problem rather than a housekeeping problem, which is the part that tends to get missed. A cloud credential is not just a secret, it is a path to whatever that credential can read, and in a healthcare application that usually means the database, the object storage holding uploaded documents, or both. The exposure is not the key, it is everything behind it.
Rotation matters more than the history rewrite, and it matters first. Purging an object from history is satisfying but it does nothing about the copies already sitting in forks, clones, and CI caches. Rotating the credential is what actually closes the door.
5. The exports nobody owns
Every application accumulates data that has escaped the application. A CSV pulled for a demo, a database dump taken before a risky migration, a bucket of uploaded documents from an early version, or a dataset extracted so someone could experiment with a model.
s3://exh-backups-dev
These are dangerous because they sit outside the access controls the app enforces so carefully. The application checks whether the requesting user is allowed to see a given patient, and the CSV on someone’s laptop does not. They also tend to have no owner, so no one is tracking retention, and they routinely outlive the reason they were created.
The remedy is inventory rather than cleverness. Knowing what exists and where is most of the work, and the answer to a surprising number of them is simply to delete the thing.
Some of them you do need to keep, and those are the ones worth scrubbing rather than deleting. When the export is a CSV or a folder of documents sitting on a workstation, redacting it in place is more practical than building a pipeline for a one-time extract, and it avoids uploading patient records to a web tool to get the job done. Philter Desktop handles that case on a single Windows machine, including scanned PDFs, with nothing leaving the computer.
What these have in common
None of these are visible in the product. You can click through the entire application, find nothing wrong, and have all five happening underneath. They are also not the result of anyone being careless, since each one is a reasonable decision made under time pressure that nobody revisited.
That is why they tend to surface at the worst moment, which is when a health system’s security team sends a questionnaire, or an investor asks how patient data is handled, or someone wants a BAA signed. The gap between a working demo and a system you can defend in front of a reviewer is mostly this list.
Detection is probabilistic wherever it runs, so treat any inventory of these as a floor rather than a proof, and validate what comes out against your own data. What matters is knowing which of the five apply to you, and where, with enough specificity that an engineer can work the list.
If you want a second pair of eyes on that, our PHI assessment for healthcare apps is a read-only review that produces exactly that list with file locations attached. If you would rather just talk it through, get in touch and we can walk through which of these are worth checking first in your stack.