Skip to main content
Case Study

A health app handling sensitive patient data. 35 findings. Strong foundations. Critical gaps at every entry point.

TierComplete
StackiOS + macOS, local database, cloud sync
Codebase500+ source files
App TypeHealth records with AI features
6
Critical
16
High
13
Medium
35
Total

What we were looking at

A health records app with on-device AI and cloud sync

This app manages sensitive patient health data entirely on the user’s device—no cloud backend, no remote database. Records sync across devices through the platform’s built-in cloud service. Users import medical records from hospitals and clinics, scan paper documents with AI-powered extraction, and manage conditions, medications, and care team members.

The app includes an on-device AI feature for clinical queries, an integration point for external AI tools, and multiple entry points: the main app, URL scheme links, a document sharing extension, and an AI tool interface that accepts commands over a local connection.

The architecture is well-structured—clean separation of models, views, and services with a solid design system. The question wasn’t whether the app worked. It was whether it was safe to ship when it handles real patient health data.

Not everything was broken

The audit found serious strengths alongside the problems

Domain modeling is excellent

The data schema accurately represents clinical relationships with proper entity separation. The audit trail captures category, source, and per-entity change records.

Medical record import pipeline

The import system handles industry-standard health data bundles with resource partitioning, patient matching heuristics, and a well-designed deduplication system.

On-device AI architecture

The AI integration for clinical entity extraction, including a hallucination detection sentinel and a search pipeline for clinical queries, all runs without sending health data to cloud services.

Clean secrets and dependencies

The entire codebase is clean of hardcoded API keys, tokens, and credentials. All dependencies are actively maintained and pinned at stable versions. No abandoned libraries.

Key Takeaway
The engineering quality was high. The gaps were at trust boundaries.

This wasn’t a case of sloppy code. The app had strong foundations, a solid design system, and thoughtful architecture. The problems were at the edges—where external input enters the app and where sensitive data leaves the protected database.

What would have caused real damage

6 findings that needed to be fixed before shipping to real patients
CriticalAny website or app can silently inject data into patient records

The app’s URL scheme for importing medical records accepts any remote URL without user confirmation or domain restrictions. A specially crafted link can fetch data from any server on the internet and write it directly to the patient file—silently, with no UI, no notification, and no log entry. Corrupted data would sync to all devices via cloud sync.

// URL scheme handler
remoteURL = URL(string: urlValue) // accepts any URL, no domain check

// when silent=true, no notification, no UI, no log to user
Suggested Approach

Never honor silent mode for remote imports. Add a domain allowlist for trusted medical record sources. Always require user confirmation before writing imported data.

CriticalAI tool interface accepts commands with no authentication

The app exposes an interface that lets external AI tools read and write patient data. This interface accepts connections from any local process with no login, no token, and no permission check. Any app on the device could silently add medications, create diagnoses, or modify clinical records—and the user would have no way to know it happened.

// AI tool interface
// No auth check before handling commands
// Writes bypass the activity audit trail

The audit also found: debug commands compiled into the production app (five developer-only routes accessible to any app or website), biometric auth silently bypassed on failure (the app falls back to open access instead of prompting for a passcode), a full plaintext dump of all AI-extracted health data written to disk on every document import, and a screen reader blocker in the onboarding flow that prevented VoiceOver users from completing setup.

Where sensitive data leaks

Health data was escaping the protected database through multiple channels
The Core Problem
Five separate paths where patient health data leaves the protected database unencrypted.

The app’s database is properly secured. But condition names, medication names, and medical codes were leaking into system logs, debug dump files, event logs, and a concentrated personal data table—all outside the database’s protections. Any backup tool, diagnostic utility, or process with container access could read them.

Beyond security

The audit covered accessibility, performance, UX, code quality, and architecture
HighAI safety check can be bypassed by a crafted document. The hallucination sentinel values are discoverable in the compiled binary.
HighNo database indexes on frequently queried fields. Imports of thousands of records would trigger full sequential scans.
HighDelete actions on clinical records have no confirmation dialog. One accidental swipe could permanently remove a condition or document.
HighDeveloper tools visible to all users in Settings. Buttons labeled “Refresh Sample Data” and “Rebuild Search Index” render in production.
Medium822 hardcoded font references bypass the existing design system tokens, blocking text resizing for users who need larger type.
MediumImporting a malicious archive file could write data anywhere on the device. No path validation after extraction.

Plus 23 more findings across security, performance, code quality, architecture, and scalability. Each with severity, code evidence, a suggested approach, and an effort estimate.

Production readiness roadmap

35 findings, organized into 4 phases by priority
Phase 1
Before shipping to patients
3-5 days

Close all critical security vulnerabilities. Auth on every entry point, remove debug routes from production, fix biometric bypass, delete the plaintext health data dump.

Phase 2
First sprint post-launch
5-8 days

Seal data leaks in logs and event files. Add database indexes. Fix delete confirmation UX. Hide developer tools. Add security tests.

Phase 3
First month
8-12 days

Adopt design system tokens consistently, add repository abstraction layer, optimize AI query pipeline, enforce data protection classes.

Phase 4
Ongoing
Continuous

Full accessibility compliance, complete design token adoption, CI lint rules for security patterns, archive file validation.

The Bottom Line
Phase 1 takes 3-5 days and closes every critical vulnerability.

This app had strong engineering. The domain modeling, the AI architecture, the import pipeline—all well-built. The audit found the gaps at trust boundaries that are invisible during normal development: where external input enters, where sensitive data leaves the protected database, and where developer conveniences ship to production. 35 unknowns became a prioritized, actionable roadmap.

Let’s figure out what you need.

Your app might have the same gaps.

This founder built a sophisticated health app with strong architecture. The audit took days. The critical fixes take hours. Find out where you stand before your users find out for you.

Get Your Audit