← Back to Pablo

Security & Responsible Disclosure

Last updated: April 2026
Most health-tech companies publish a security page describing how careful they are. We publish the actual pentest reports — including the findings that weren't clean yet — because HIPAA compliance is a process, and operators deserve to see it.

Why this page exists

Pablo is AGPL-3.0 open source. The code is public, the architecture is public, and the security testing should be too. If you're considering Pablo — hosted by us or self-hosted — you shouldn't have to take our word for the security posture. You should be able to read the actual test and see what was found.

Technical implementation

This is the implementation detail behind the commitments in our BAA and Privacy Policy. We keep the receipts here, on a page that engineering can update without rewriting a privacy policy, so the values you read are the values that ship.

In transit

At rest

Tenant isolation

Identity and access

AI processing

Audit logging and behavioral monitoring

Backup and retention

Egress allowlist

The application boundary is allowlisted to the subprocessors named in the BAA §5.2 and Privacy Policy §5. The weekly internal pentest probes for egress to non-allowlisted hosts; any finding is surfaced in the next dated pentest report and triggers a release hold while it is investigated. The release hold is operational today (an on-call engineer reviews the report and pauses release) — automating it as a hard CI gate is on our roadmap.

Our disclosure pledge

If we find something, you'll see it.

For serious issues: we fix it, ship the patch, and notify operators privately first — then publish full detail within 30 days. Findings that don't meaningfully help an attacker publish same-day. If a vulnerability ever leads to actual unauthorized PHI access — a breach under 45 CFR §164.410 — we notify on confirmation, not on the statutory clock, and inside whichever deadline (federal or state) applies to the affected jurisdiction.

That's deliberately stricter than what HIPAA requires. The Breach Notification Rule (45 CFR §164.400–414) only triggers on actual unauthorized access to PHI — not on the vulnerabilities that could have led there. We publish those anyway. For Critical findings against deployments that can't patch in an hour, a short embargo (typically 7–30 days depending on severity) protects users while patches roll out, consistent with how Django, Rails, and the Linux kernel coordinate security releases.

How we test

This isn't a checkbox. We built our own pentest tool — a custom LLM agent (open source, in our repo) that drives the scanners, cross-references our BAA manifest on every external egress, maps each finding to the specific HIPAA Security Rule control it touches, and tracks closure week-over-week.

This is our primary technical evaluation today. As Pablo grows, the program will grow with it.

A week-by-week authorized penetration test runs against the deployed Pablo app. The methodology is mapped to the HHS Office for Civil Rights' expectations for a qualified pentester of a HIPAA-regulated system:

Every finding is tagged with the specific CFR section it affects (a CFR mapping) so operators and auditors can see which control the finding speaks to. Examples: an audit-logging gap maps to §164.312(b); a cross-tenant access issue maps to §164.308(a)(4) and §164.312(a)(1).

Reproducibility — run it yourself

The entire pentest methodology ships in the repo as an agent skill, with parallel implementations for Claude Code (.claude/skills/pentest/SKILL.md) and the Gemini CLI (.gemini/skills/pentest/SKILL.md). The same playbook also runs unattended in a hardened container as a scheduled Cloud Run Job — that's what produces the dated reports below. Two different LLMs running the same playbook surface different things, so we run both deliberately.

If you self-host Pablo, you can run the same owner-authorized test against your own deployment with /pentest — no black box, no "trust us."

Published reports

Each run produces a dated report. We publish them as we go — including ones with open findings. Findings stay in the report until they're closed; closed findings are re-tested the following week and noted in the next report's "items tested clean" section. Browse the archive in the public repo.

DateReportStatus
2026-05-17 Pentest report (MD) 0 CRITICAL · 2 HIGH (both resolved or mis-attributed) · 1 LOW · 2 INFO. PABLO-API-500 (POST /api/patients 500 on freshly-provisioned tenants) closed by PR #203 — missing tenant database configuration. PABLO-AUDIT-01 (audit_logs reported empty for 24h) mis-attributed — query-side issue, no audit-log outage. PABLO-TLS-01 (CBC ciphers offered on TLS endpoint) — will be fixed next run.
2026-05-11 Pentest report (MD) 0 CRITICAL · 2 HIGH (HIPAA impact: None — both are transitive dependency CVEs with no PHI request path; patching anyway in the next dependency sweep) · 1 INFO carry-over · 2 prior findings resolved-this-run. PABLO-004 (urllib3 2.6.3, CVE-2026-44432 + CVE-2026-44431) — transitive only; the deployed application's HTTP stack is httpx (which doesn't sit on urllib3) and backend/app/ contains zero direct import urllib3. Upgrading to 2.7.0+. PABLO-005 (mako 1.3.11, CVE-2026-44307) — transitive via alembic; the CVE specifically requires Windows backslash resolution and Pablo runs on Linux Cloud Run, and there is zero import mako in application code. Upgrading to 1.3.12+. PABLO-001 (pip 26.0.1) — INFO carry-over, already accepted risk in VULNERABILITY_EXCEPTIONS.md (no upstream fix, build-time only). PABLO-002 (05-10 audit pipeline) closed by PR #145 — root cause was deployed-schema drift, not the AuditService component named in the 05-10 report; this run's closed-loop check confirms the audit pipeline is operational. PABLO-003 (missing exception log, from the 05-11 01:49Z degraded run) closed by PRs #147 + #148 — VULNERABILITY_EXCEPTIONS.md is now baked into the pentest image and read correctly.
2026-05-10 Pentest report (MD) 1 HIGH (mis-attributed — PABLO-002 reported HTTP 500 on POST /api/patients and blamed AuditService; the real cause was deployed-schema drift on the patients table. Fixed: migrations re-applied and the prod DB reconciled to head) · 1 MEDIUM (PABLO-001 carry-over — pip 26.0.1 CVE-2026-3219 / -6357, accepted risk: no upstream fix exists, build-time only, no PHI reachability — documented in VULNERABILITY_EXCEPTIONS.md)
2026-05-03 Pentest report (MD) 1 HIGH (false positive — PABLO-002 flagged audit_logs empty over 24h, but the same run's closed-loop test successfully wrote and read back an audit row, so the pipeline is alive; this was an idle-deployment signal, not a real § 164.312(b) failure — see the report's Erratum block) · 1 MEDIUM (PABLO-001 vulnerable deps — closed same day in PR #108) · narrator-prompt fix to prevent recurrence in PR #111
2026-04-30 Pentest report (MD) 1 MEDIUM (PABLO-001 vulnerable deps — closed 2026-05-03 by PR #108) · 1 LOW from 04-23 closed
2026-04-23 Pentest report (MD) 1 LOW open · 5 of 6 from 04-16 closed
2026-04-16 Pentest report (MD) · PDF 6 findings (2H/3M/1L) · 5 closed by 04-23 · 1 LOW carried forward

Methodology: HIPAA Pentest Guide (what OCR expects, what we do, CFR mapping, severity rubric, rules of engagement).

If you're self-hosting

Pablo is AGPL — you can (and many will) run it on your own infrastructure. Your security posture is your own, but we'll do everything we can to make it defensible:

Reporting a vulnerability

If you find something in Pablo — the hosted product, the OSS codebase, or a deployment you're running — email security@pablo.health. We read it.

What helps:

We'll acknowledge within 72 hours, work a fix with you, and publish per the policy above. We don't currently run a paid bug bounty — but we do credit every valid report by name in the pentest report archive.

What this page does not cover