Healthcare apps fail security review far more often than most teams expect, and it's rarely because of one catastrophic flaw. It's usually five or six moderate-severity issues that, together, add up to "not production-ready for PHI." Having sat through (and caused) a fair number of these reviews, here's a breakdown of where they actually go wrong — at the architecture and code level, not the compliance-checklist level.
The gap between "HIPAA compliant" and "actually secure"
HIPAA's Security Rule is deliberately non-prescriptive. It requires "reasonable and appropriate" safeguards across three categories — administrative, physical, and technical — but doesn't hand you a spec sheet. That ambiguity is exactly why so many teams ship something that satisfies a compliance checklist while failing an actual penetration test. A signed Business Associate Agreement and an AES-256 checkbox don't mean the implementation is sound.
The technical safeguards that matter most in practice: access control, audit controls, integrity controls, and transmission security. Almost every failed review traces back to a gap in one of these four.
- PHI leaking into places nobody thought to check
This is the single most common finding. Protected health information ends up somewhere it was never supposed to be:
Application logs. A console.log(patientData) left in during debugging, or worse, a logging library configured to serialize entire request/response objects — including headers with auth tokens and bodies with patient names, DOBs, and diagnosis codes — straight into a log aggregator that wasn't scoped for PHI.
Crash reporting tools. Sentry, Crashlytics, and similar tools capture stack traces and local variable state by default. If a crash happens inside a function holding patient data in scope, that data can end up in a third-party crash dashboard that was never covered under a BAA.
Third-party analytics and SDKs. Firebase Analytics, marketing pixels, or even A/B testing tools initialized without care can pick up screen names, form field values, or user identifiers that map back to a patient. The SDK doesn't know it's touching PHI — it just does what analytics SDKs do.
Push notification payloads. A notification that reads "Your test results for [Condition] are ready" is PHI sitting in a push payload that transits Apple's or Google's infrastructure and lands in a device's notification tray, visible on a lock screen.
The fix isn't "be more careful." It's structural: PHI needs to be tagged at the data-model level so it can be excluded from logging middleware, redacted before it reaches crash reporters, and never handed to a third-party SDK that isn't under a BAA — enforced by lint rules or a data-classification layer, not developer discipline.
- Local storage and device-side data at rest
Mobile healthcare apps routinely fail on this one. Common patterns that trip reviews:
Unencrypted SQLite or Realm databases storing cached patient records for offline access, with no additional encryption layer beyond the OS's default file protection.
Sensitive data in UserDefaults / SharedPreferences, which are not encrypted by default on either platform and are trivially readable on a jailbroken or rooted device.
Screenshots and app-switcher snapshots. iOS and Android both capture a snapshot of the current screen when an app backgrounds, for the app-switcher UI. A patient chart left visible on screen gets cached as an image on disk unless the app explicitly blanks the screen on applicationDidEnterBackground (iOS) or sets FLAG_SECURE (Android).
Keyboard caches and autocorrect dictionaries learning from free-text fields where patients type symptoms or medication names.
None of these show up in a functional QA pass. They show up when someone pulls the device's file system in a review and greps for patient identifiers.
- Broken or oversimplified access control
Authorization bugs are the second-most common category, and they tend to fall into a few recognizable shapes:
IDOR (Insecure Direct Object Reference). An API endpoint like GET /api/patients/{id}/records that checks authentication (is this a valid logged-in user?) but not authorization (is this logged-in user allowed to see this specific patient's records?). This is consistently one of the highest-frequency findings in healthcare API reviews, precisely because patient record IDs are often sequential or easily guessable.
Role checks enforced client-side only. A doctor-only screen hidden in the UI for patient-role users, but the underlying API endpoint has no server-side role check — meaning the "hidden" screen's data is one crafted request away from being fully accessible.
Overly broad OAuth scopes, especially in apps that integrate with FHIR-based EHR systems (Epic, Cerner). Requesting patient/*.read when the app only needs patient/Observation.read is a common shortcut that turns a minor breach into a full record exposure.
Session tokens that don't expire meaningfully. Long-lived JWTs with no server-side revocation path mean a stolen token stays valid long after a user reports a lost device.
- Transmission security gaps that aren't "no HTTPS"
Almost nobody ships a healthcare app without TLS anymore — that's not where the failures are. The real gaps are subtler:
Certificate pinning absent or misconfigured, leaving the app vulnerable to MITM interception on compromised networks or via a malicious VPN/proxy profile.
Mixed content in hybrid or WebView-based apps, where a native shell correctly enforces TLS but an embedded WebView loads a resource over plain HTTP.
Third-party SDKs making their own network calls outside the app's primary TLS configuration, bypassing pinning entirely.
API responses over-fetching. An endpoint that returns a full patient object when the screen only needs three fields increases the blast radius of any transmission-layer compromise.
- Audit logging that exists but doesn't actually help
HIPAA requires audit controls — but "we have logs" and "we have logs that let you reconstruct who accessed what PHI and when" are very different bars. Common failure: logs capture that an API endpoint was hit, but not which patient record was returned in the response, making it impossible to answer the actual audit question ("who viewed patient X's chart on this date") without cross-referencing multiple systems that were never designed to be joined.
What actually gets a healthcare app through review
The teams that pass consistently share a few habits:
PHI is classified at the schema level, not identified ad hoc by whoever's writing a given feature. A field is either PHI or it isn't, and that flag drives logging exclusion, encryption requirements, and access-control rules automatically.
Authorization is enforced server-side, on every endpoint, by default — not as a special case added when someone remembers.
Third-party SDKs go through a data-flow review before integration, not after a reviewer finds an unexpected outbound network call.
Security review happens before the compliance checklist, not as a substitute for it. A signed BAA with a vendor doesn't secure your architecture; it just allocates liability if the architecture fails.
Security review failures in healthcare apps are rarely about missing a big, obvious control. They're about PHI moving through paths nobody mapped — a log line, a crash report, a cached screenshot, an over-scoped API response. Mapping every place patient data actually flows, not just the places it's supposed to flow, is the difference between an app that passes review and one that needs three more sprints to get there.
Top comments (1)
This is one of the more practical explanations I've seen of why healthcare apps fail security review. The key point is that compliance checklists and actual security posture are not the same thing. At Dev Technosys, we've found that the most effective approach is to treat PHI as a first-class data category throughout the architecture—from logging middleware and crash reporting to analytics integrations and notification services. The issues you highlighted, especially accidental PHI leakage through logs, SDKs, and push payloads, are often overlooked during development because they don't appear in the main application flow. Building automated safeguards such as data-classification layers, redaction pipelines, and CI/CD security checks is usually far more reliable than depending on individual developers to remember every compliance rule. This breakdown does an impressive job of showing where the real technical risks actually live.