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.
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.
app.pablo.health use TLS. Plain HTTP requests are rejected with HTTP 400 by the application's HTTPS-enforcement middleware.Strict-Transport-Security: max-age=63072000; includeSubDomains; preload (two years, with subdomains, preload-list eligible). The two-year window is the IETF + browser-vendor recommendation for preloaded production sites; longer is more secure because the browser remembers the HTTPS-only commitment longer.practice_<id>). Application code resolves the practice schema from the authenticated email at the start of every request and sets the database session's search_path before any handler runs.FORCE-enabled on every table that carries a user_id column. The RLS policy fails closed when the per-request user context (app.current_user_id) is unset, so a query that somehow ran outside our middleware returns zero rows rather than leaking across users.check_revoked=true flag on every request, not just at sign-in, so a revoked token cannot continue to ride a long-lived browser tab.api.openai.com, api.anthropic.com, or generativelanguage.googleapis.com. The weekly internal pentest probes for egress to those hosts and surfaces any finding in the next dated report; an active finding triggers a release hold.generate-content path Pablo uses) is disabled on our project.hard_purge_cron, audit_retention_cron, audio_retention_purge).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.
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.
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).
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."
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.
| Date | Report | Status |
|---|---|---|
| 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).
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:
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.