Security at Dental Refer
We treat dental PHI the way the regulations treat it: as data with real obligations to the patient, the provider, and the practice. Every control below is engineered, not asserted. Where it's verifiable end-to-end, we say so.
Encryption
- AES-256-GCM field-level encryption, on write, for patient-record identifiers (name, birth date, phone, email) and the free-text clinical content of referrals, referral letters, specialist reports and messages — on top of storage-level encryption at rest
- Decrypting read path (Phase C) live for each of those: patient records, referrals, referral letters, specialist reports and messages; a row with no encrypted copy is read from the original column, which is still written alongside the encrypted copy
- TLS 1.2+ in transit (HSTS preload, 63072000 max-age)
- PBKDF2-SHA512 password hashing, 210,000 iterations
- Per-org credential storage encrypted in integration_credentials table
Identity & access
- HttpOnly + Secure + SameSite session cookies
- Sessions end at most 30 minutes after the last keyboard, pointer or touch input and 12 hours after sign-in; background notification checks and page loads do not extend a session
- Mandatory two-step sign-in for every account: a password plus a one-time code (from an authenticator app, a single-use backup code or, where enabled, an email to the account's verified address; platform administrators use an authenticator app or backup code only), or a device the user chose to remember after such a code, for up to 30 days by default (never more than 90; administrators always enter a code)
- Role-based access control (5 organization roles + platform admin)
- Organization-scoped data isolation; org_id derived server-side from session
Audit & integrity
- Immutable, append-only audit_log (PostgreSQL trigger-enforced)
- Hash-chained audit entries (prev_hash chain) — verified daily
- Every PHI read, write, and attachment download audited
- No PHI in audit metadata — only hashed identifiers + scoped action codes
Application security
- Strict TypeScript across all surfaces; Zod schema validation on API request input
- Rate limiting on auth, search, and PHI endpoints
- CSP, X-Frame-Options DENY, Permissions-Policy lockdown
- SAST + dependency scanning + secret scanning on every PR
Attachments & file safety
- MIME-type allowlist on upload; for referral attachments, image, PDF and DICOM files are also checked against their own bytes
- Max 20 MB per file
- Downloads of uploaded files withheld until the file passes a malware scan: Amazon GuardDuty Malware Protection scans every upload, and an uploaded file is released only when GuardDuty finds no threat and the platform's own content checks pass (a search of every file for the standard antivirus test signature, plus a structure check of PDF, PNG, JPEG and GIF files), so no uploaded file is released unscanned
- Signed URLs with short TTL (15 min) for downloads
- Files stored in Amazon S3 (us-east-2) under our AWS Business Associate Addendum, in a private bucket that is versioned and encrypted at rest; files stored before the move to S3 stay with the previous storage provider until they are deleted, as /subprocessors discloses
Operations
- Production deploys via Vercel with rollback within 5 min
- Health-check endpoint with PHI key fingerprints and service status
- Documented incident response runbook with severity levels and response targets
- Postgres logical backups + point-in-time recovery (Neon)
- No PHI in logs or error responses; the eligibility, fax and email integrations that carry PHI run on BAA-covered vendors listed on /subprocessors
Built but not switched on
A second layer of active defense — blocking a session after anomalous decrypt volume — is written and tested but disabled in production; no session is blocked by it today, and it is listed here rather than above because a control behind a switch is not a control. The same goes for decoy-record rotation, which is designed and not yet implemented. This section stays until they are live, at which point they move up into the list above.
Reporting a vulnerability
Email security@dentalrefer.com with reproduction steps and impact. We aim to acknowledge reports within 24 hours and to triage them within 72 hours, and we disclose after a fix in coordination with the reporter. We do not currently run a paid bounty program.
Do not email patient information (names, dates of birth, clinical details or images) to any Dental Refer address. Send patient information only through Dental Refer itself, after signing in.