EMStool LLC — Cadence MIH Scheduling Platform

HIPAA Security Risk Analysis

Policy #: HIPAA-SEC-002 Effective Date: June 2, 2026 (rev. July 16, 2026) Version: 1.1 Next Review: June 2, 2027 Security Officer: Jacob Russell

1. Purpose & Legal Basis

This Risk Analysis identifies and evaluates potential risks and vulnerabilities to the confidentiality, integrity, and availability of electronic Protected Health Information (ePHI) maintained by EMStool LLC in the operation of the Cadence MIH Scheduling Platform.

45 CFR §164.308(a)(1)(ii)(A) requires covered entities and business associates to conduct an accurate and thorough assessment of the potential risks and vulnerabilities to the confidentiality, integrity, and availability of ePHI held by the organization.

2. Scope

This analysis covers all systems, infrastructure, and processes involved in the storage, processing, and transmission of ePHI within the Cadence platform, including:

Deployment model: each client runs Cadence on its own dedicated hardware — either an appliance EMStool provides or the client's own server, in the client's own facility — reachable only via an outbound tunnel. There is no shared/multi-tenant database; each client's MariaDB and web-server containers are fully isolated to that client's hardware. EMStool also operates a small amount of its own non-client infrastructure (Bender) used for software development and a customer-facing demo/trial instance — that infrastructure holds no real client ePHI and is described separately in Asset 6 below.

3. Information Assets Containing ePHI

Asset 1: Primary Application Databases (Client Deployments)
Location: One dedicated MariaDB container per client deployment, on that client's own designated hardware (EMStool-provided appliance or the client's own server, in the client's own facility)
ePHI contained: Patient demographics, dates of birth, phone numbers, addresses, clinical notes, appointment history, medication records, lab results, insurance information, diagnosis codes
Protection: MariaDB InnoDB tablespace encryption (AES-256-CBC), BEFORE DELETE/UPDATE triggers on audit_log, dedicated audit_writer DB user, bcrypt password hashing
Asset 2: Patient File Uploads
Location: /config/www/uploads/ inside each customer's SWAG container, Bender
ePHI contained: Photos and documents attached to patient notes (may include clinical images, ID documents)
Protection: AES-256-GCM encryption at rest (.enc files), session-authenticated serve_image.php delivery, MIME type validation
Asset 3: Encrypted Backup Files
Location: /config/backups/ (local), Backblaze B2 bucket (customer-configured)
ePHI contained: Full database dump including all patient records
Protection: GPG AES-256 symmetric encryption before write; .sql.gpg files unreadable without passphrase; B2 upload of pre-encrypted files only
Asset 4: Network Transmission
Location: All traffic between users and Cadence servers
ePHI contained: All patient data in transit during normal application use
Protection: Cloudflare Zero Trust Tunnel (TLS 1.3); no open inbound ports on origin server; DDoS protection
Asset 5: Encryption Keys and Credentials
Location: Per-customer MariaDB encryption keyfile under /mnt/user/appdata/mariadb-<instance>/config/encryption/keyfile (Bender); /mnt/zrust/Byte/EMSTool/secure/cadence-data-keys/ (Cosmo ZFS backup)
ePHI contained: Keys that decrypt all ePHI above — compromise = full data exposure
Protection: chmod 600, root-only access, off-machine backup on ZFS pool. No HTTP-reachable retrieval path exists — key access requires direct SSH/filesystem access to the server, same as any other server secret (as of July 2026; a prior admin-download page was removed for not meeting this bar).
Asset 6: EMStool's Own Infrastructure (Bender, 192.168.0.13)
Location: Single physical host owned and operated by EMStool, Unraid 7.x, Docker containers on the proxynet/video-net internal networks — no container has an open inbound port to the internet; all external access is via Cloudflare Tunnel
Purpose: This host runs EMStool's own operational tooling and a demo/trial instance for prospective clients to evaluate — it does not run any client's production deployment. Real client deployments each run on separate, client-designated hardware (see Section 2 Scope) and are not part of this asset.
ePHI contained: None of significance — the demo instance runs seed/dummy data only, never real patient records. See table below.
Protection: Host-level access restricted to Security Officer; container isolation; internal-only Docker networking
ContainerImagePurposeePHI Exposure
MariaDB-schedulermariadb:latestDatabase for the public demo/trial instance (scheduler.emstool.com) — prospective clients try Cadence hereNone — seed/dummy data only, no real patient records
MariaDB-licensemariadb:latestLicense/billing metadata for client deploymentsNone — no patient data
MySQLmysql:latestLegacy DB backing swag-emstool's misc subdomains (users db, unrelated jeopardy game db)None
swag-schedulerlscr.io/linuxserver/swagWeb/app server + TLS termination for the demo/trial instance, scheduler.emstool.comNone — seed/dummy data only, no real patient records
swag-licenselscr.io/linuxserver/swagLicense server + Command Deck ops console, license.emstool.comNone — no patient data
swag-emstoollscr.io/linuxserver/swagPublic marketing site + legacy subdomains, emstool.comNone — no patient data
swag-suspendednginx:alpineStatic "service unavailable" page shown during instant client suspensionNone
cadence-provisionercadence-provisioner (local image)One-click new-deployment provisioning; holds Docker socket accessNone directly, but privileged
swag-videonode:20-alpineVideo consult signaling server (WebRTC offer/answer relay)Call signaling metadata only — no media, no chart data
redis-videoredis:7-alpineEphemeral signaling state for swag-videoCall signaling metadata only
coturncoturn/coturnSelf-hosted TURN relay — test/isolation use only, not production (production TURN is Cloudflare Realtime)Would relay encrypted (SRTP) call media if used — not currently in the production call path
osrm-dfw / osrm-usaosrm/osrm-backendRoute optimization engines (DFW-metro extract + full-USA extract)Receives patient address coordinates for routing — no other PHI
Nominatimmediagis/nominatimSelf-hosted geocoding (address → lat/lng), internal only — no public Nominatim fallbackReceives patient addresses for geocoding — no other PHI
gotenberggotenberg/gotenbergPDF generation for end-of-day reports and chart exportsReceives full chart/report content to render as PDF
CF-TUNNEL-DARYL / Unraid-Cloudflared-Cadencefigro/unraid-cloudflared-tunnelCloudflare Zero Trust Tunnels — sole external ingress pathePHI in transit passes through per client deployment (TLS-encrypted end-to-end, Cloudflare does not decrypt at this hop)

Route optimization, geocoding, PDF rendering, video signaling, and the tunnel ingress pattern above run identically inside each client's own deployment (on the client's own hardware) — this table documents EMStool's own copy of that same stack, used for development and the demo instance, not a client's live data.

Asset 7: Third-Party Vendors
Tracked separately with full risk ratings and BAA status — see Vendor Documentation and Vendor Risk Register. Current active vendors: Cloudflare (Tunnel/CDN + Realtime TURN), Backblaze B2 (encrypted backups), Resend (transactional email, no PHI), Telnyx (SMS, no PHI).

4. Risk Assessment Matrix

Each threat is rated by Likelihood (1–3) and Impact (1–3). Risk Level = Likelihood × Impact:

ScoreRisk LevelResponse Required
7–9CriticalImmediate remediation required
5–6HighRemediation within 30 days
3–4MediumRemediation within 90 days or accepted with controls
1–2LowMonitor; accept with existing controls

5. Threat & Vulnerability Assessment

Threat Like. Impact Risk Current Controls Residual Risk / Action
T-01: Unauthorized remote access to application server 23High (6) Cloudflare Zero Trust Tunnel (no open ports); bcrypt auth; session timeout; rate limiting; MFA available; SSH key-only Medium — Enable MFA enforcement for all users
T-02: Physical theft or unauthorized access to server hardware 13Medium (3) Servers in locked room at private residence; access restricted to Security Officer; MariaDB data encrypted at rest (AES-256) Low — Acceptable with physical security policy in place
T-03: Ransomware or malware infection 23High (6) Encrypted backups on B2 (off-site); Docker isolation limits blast radius; no direct internet exposure; Unraid OS separation Medium — Off-site B2 backups enable recovery; test restore procedure quarterly
T-04: Credential theft (phishing, weak passwords) 23High (6) Bcrypt password hashing; 5-attempt lockout; TOTP MFA available per user; SSH key authentication for server access Medium — Enforce MFA for all users via admin toggle
T-05: Insider threat (unauthorized patient data access) 22Medium (4) HIPAA audit log (append-only via DB triggers) records all access; org-tree scoping limits data visibility; role-based access control; company access gates Low — Quarterly audit log review by Security Officer
T-06: Loss or exposure of encryption keys 13Medium (3) Key backed up to ZFS Byte pool (Cosmo); OneTimeSecret email delivery; chmod 600; root-only access; documented in Physical Security Policy Low — Annual key backup verification required
T-07: Network interception (man-in-the-middle) 13Medium (3) TLS 1.3 via Cloudflare; no plaintext HTTP permitted; HTTPS enforced in _auth.php; Cloudflare WAF and DDoS protection Low — Cloudflare handles TLS termination and certificate management
T-08: Backup failure or corruption 22Medium (4) Automated scheduled backups; validation step decrypts and counts tables; backup_log records success/failure; B2 off-site copy Low — Test restore from B2 quarterly; alert on backup failure
T-09: Third-party vendor breach (Cloudflare, Resend, Backblaze B2) 12Low (2) Cloudflare: sees only encrypted TLS traffic. Resend: password resets only, zero PHI. B2: receives pre-encrypted .sql.gpg files only — no readable PHI Low — Vendor documentation maintained; annual review
T-10: Patient address exposure via Nominatim geocoding 21Low (2) Self-hosted Nominatim deployment in progress (build running on Cosmo); no external geocoding API calls planned post-deployment Low — Complete Nominatim self-hosting; switch app URLs
T-11: Application vulnerability (SQL injection, XSS) 13Medium (3) All DB queries use PDO prepared statements; all output passed through htmlspecialchars(); esc() helper for JS DOM; Cloudflare WAF Low — Code review on all new features; no user-controlled SQL
T-12: Docker container escape or misconfiguration 13Medium (3) Per-customer isolated Docker networks; no privileged containers (except SWAG NET_ADMIN); no host port bindings; MariaDB not exposed externally Low — Keep Docker and base images updated
T-13: Workforce member HIPAA policy violation 22Medium (4) Sanctions Policy documented and signed; Workforce Training Policy in place; audit log captures all PHI access; access revoked immediately on termination Low — Annual training completion required; quarterly audit log review
T-14: Server hardware failure (no redundancy) 22Medium (4) Encrypted B2 backups enable recovery to new hardware; Docker containers restart automatically; UPS protects against power events Medium — Document RTO/RPO targets; test full restore procedure

6. Summary of Open Risk Items

#ThreatCurrent RiskMitigation ActionTarget Date
1 T-01, T-04: Unauthorized access / credential theft Medium Enable MFA enforcement toggle for all users (Admin → Settings → Require MFA) Before first customer deployment
2 T-03: Ransomware recovery Medium Document and test full restore procedure from B2 encrypted backup Q3 2026
3 T-10: External geocoding exposure Low Complete self-hosted Nominatim deployment and switch app URLs After Daryl SSD upgrade
4 T-14: Hardware failure RTO Medium Define Recovery Time Objective and test restore to clean hardware Q3 2026

7. Current Security Controls Summary

Control CategoryControls in PlaceStatus
Encryption at Rest MariaDB InnoDB AES-256 (all tables); file upload AES-256-GCM; backup GPG AES-256 ✅ Complete
Encryption in Transit TLS 1.3 via Cloudflare Zero Trust; HTTPS enforced; no open inbound ports ✅ Complete
Access Control Role-based (10 levels); org-tree scoping; company access gates; session timeout (4hr); rate limiting; MFA available ✅ Complete — MFA enforcement pending
Audit Logging Append-only audit_log (DB triggers block delete/update); dedicated audit_writer user; all PHI access logged ✅ Complete
Backup & Recovery Automated scheduled backups; GPG encryption; B2 off-site; validation on every backup; retention management ✅ Complete — restore test pending
Key Management InnoDB key on server; backup copy on ZFS Byte pool (separate machine); OneTimeSecret email delivery ✅ Complete
Physical Security Locked server room; restricted access; documented in Physical Security Policy ✅ Documented
Workforce Policies Sanctions Policy; Physical Security Policy; Workforce Training Policy; Breach Notification Procedure; Security Officer designated ✅ Complete — Risk Analysis document (this document)
Vendor Management Vendor documentation completed; no PHI to Resend or B2 (pre-encrypted); Nominatim self-hosting in progress ⚠ Nominatim pending

8. Risk Acceptance Statement

Based on this analysis, the Security Officer determines that:

9. Review Schedule

This Risk Analysis must be reviewed and updated:

Security Officer Signature
Jacob Russell, Security Officer
Date
June 2, 2026