Security
This page is written from an internal control audit dated 11 August 2026 in which every statement below was verified against a live system response, a configuration query, or a line of code — not from a marketing brief. Where a control is missing or not yet operating, it is listed in What we do not claim rather than omitted.
| PHI field encryption | Protected-health-information fields are individually encrypted with AES at the application layer before they reach the database, in addition to full-disk encryption of the database itself. |
|---|---|
| Key custody | The encryption key is held in AWS Secrets Manager and injected into the running task at start-up. It is not in source control, not in a container image, and not in an environment variable in any build artifact. |
| Database encryption | Amazon RDS storage encryption with a customer-managed KMS key, automatic annual key rotation enabled. Automated backups and snapshots inherit the same key. |
| Transport | TLS 1.2 and 1.3 only — TLS 1.0 and 1.1 are refused at the load balancer (ELBSecurityPolicy-TLS13-1-2-2021-06, live-tested). Plain HTTP is redirected to HTTPS. HSTS is sent with a one-year max-age including subdomains. |
| Database connections | Connections to the database require TLS (rds.force_ssl = 1). |
| Object storage | Both S3 buckets: KMS default encryption, versioning on, all four public-access blocks on. |
| Enforced by the database, not by queries | Tenant isolation is enforced by PostgreSQL Row-Level Security — a policy on the table itself, not a WHERE clause an engineer can forget. |
|---|---|
| The application role cannot bypass it | The serving database role is NOSUPERUSER and NOBYPASSRLS, and policies are declared FORCE ROW LEVEL SECURITY so they bind even the table owner. |
| Coverage | 113 of the 114 tenant-scoped tables carry an active, forced row-security policy. The one exception is listed under “What we do not claim” below. |
| Context cannot leak between requests | Tenant context is set as a transaction-local session variable and re-applied on every transaction begin, so a pooled connection cannot carry one tenant's context into another tenant's request. |
| Proven, not asserted | During the disaster-recovery drill on 2026-07-07, the application role without tenant context returned 0 rows from users, notes and episodes on a restored production snapshot. |
| Append-only audit trail | Every access and privileged action is written to an audit trail that is append-only, enforced by database triggers. The application role cannot modify or delete audit history. |
|---|---|
| No PHI in the audit trail | Audit records carry identifiers, action verbs and timestamps only — no clinical content — so they can be retained long term and exported to a customer SIEM. |
| Impersonation is stamped | Support “view as” sessions are read-only and every resulting audit row records the operator who initiated them. |
| Infrastructure audit | AWS CloudTrail is enabled across all regions with log-file validation and KMS encryption. Log groups retain 400 days. Alarms fire on root-account use, trail configuration change and administrative user creation. |
| Network position | Application servers run in private subnets with no public IP address. The database is not publicly accessible and accepts connections only from the application security group. |
|---|---|
| Identity | There are no long-lived IAM users in the production account. All human access is a short-lived assumed-role session. |
| Secrets | All ten runtime secrets are held in AWS Secrets Manager and injected at start-up. No secret value is stored in an environment variable, a container image, or source control. |
| Least privilege | The task role's model-inference permissions are scoped to named model families; its Cognito permission is scoped to one user-pool ARN and its email permission to one identity. The execution role can read exactly nine named secret ARNs. |
| Containers | The application container runs as a non-root user (uid 10001). |
| Availability | Database is Multi-AZ with deletion protection. Two application tasks run behind the load balancer with CPU target-tracking autoscaling. |
| SQL injection | All database access is parameterized. A repository-wide scan of all 211 raw-SQL call sites found zero dynamically constructed statements. |
|---|---|
| Code execution | The application contains no eval, exec, or shell-execution paths. |
| Static analysis | bandit runs on every change and gates at zero medium-or-higher findings. |
| Dependency, image and SBOM scanning | pip-audit, trivy and a CycloneDX SBOM run on every change to main and weekly on a schedule. Accepted advisories are documented individually with a reachability analysis and a named permanent fix. |
| Rate limiting | Per-IP rate limiting at the edge and in the application, with tighter limits on login, signup, token and password-reset endpoints. Request bodies are size-capped, including chunked uploads. |
| Response headers | X-Frame-Options: DENY, X-Content-Type-Options: nosniff, a restrictive Permissions-Policy (microphone on our own origin only; camera, geolocation, payment and USB denied), Referrer-Policy, and Cross-Origin-Opener-Policy. |
| Cross-site request forgery | Not applicable by design: the API authenticates with an Authorization: Bearer header, never an ambient cookie, so there is no cross-site request to forge. |
| Vulnerability disclosure | Published at /.well-known/security.txt (RFC 9116). Reports go to security@tebscribe.com. |
| Where inference runs | All large-language-model inference runs on Amazon Bedrock inside our own AWS account, under our signed AWS Business Associate Agreement. |
|---|---|
| Business Associate Agreements | Signed with AWS and with Deepgram, our speech-to-text provider (countersigned 2026-08-02). |
| No training on your data | Speech-to-text requests are sent with the vendor's model-improvement program explicitly opted out, on both the batch and the realtime path, guarded by an automated regression test that fails the build if the flag is dropped. |
| On-device option | Free-tier dictation runs on the device; that audio never leaves the phone. |
| Subprocessor register | We maintain a register naming every third party that processes customer data, what it processes and its BAA status. Available on request with a security questionnaire. |
| Backups | Automated database backups retained 35 days, with point-in-time recovery available. Backups inherit the database's customer-managed KMS key. |
|---|---|
| Restore has actually been tested | On 2026-07-07 we restored a production snapshot to a throwaway instance and measured a recovery time of 2 minutes 39 seconds against a four-hour objective; integrity was confirmed on record counts only. The procedure is written up as a repeatable runbook. This is one dated drill, not a demonstrated cadence. |
What we do not claim
A security review is faster when the gaps are on the first page. These are ours, as of 11 August 2026.
- Independent assurance. We hold no SOC 2 report of any type. We have engaged an external advisor and are working toward SOC 2 Type II; the observation window has not started. We will not imply a report exists before one does.
- Penetration testing. No third-party penetration test has been performed to date.
- Multi-factor authentication. Multi-factor authentication is available in our identity provider but is not currently required for every user. Requiring it is our next authentication change.
- Web application firewall. An AWS WAF is attached to the load balancer, but only the per-IP rate-limit rule takes action. The AWS managed rule groups run in count mode today — they log, they do not stop traffic. We will say so rather than list a firewall we are not enforcing.
- Threat detection. We do not run a security operations centre, a managed detection service, or around-the-clock human monitoring. Detection today is CloudTrail alarms on specific privileged events plus availability alarms.
- Content Security Policy. Our CSP is deployed in report-only mode. It is not enforcing, so we do not list it as a control.
- Audit-log integrity. The audit trail is append-only and hash-chained by design, but chain verification is not yet running on a schedule in production and the chain head is not yet anchored to write-once storage. Until both are true we claim append-only enforcement, and no more than that.
- Secret rotation. Automated rotation is not enabled on our runtime secrets. (One exception is permanent by design: rotating the field-encryption key would render existing encrypted records unreadable, so that key is re-keyed only through an envelope-encryption migration.)
- Row-level security coverage. One tenant-scoped table — a counter of clinical-calculator search terms, holding no note content — does not yet carry a row-security policy. It is the single gap in the wall and it is being closed.
- Recovery point objective. Our restore drill exercised the snapshot path. We have not yet drilled point-in-time recovery, so we do not publish a recovery-point objective.
- Enterprise single sign-on. SAML and OIDC enterprise identity providers are not available today. Google and Apple sign-in are.
- HIPAA. HIPAA has no certification scheme and no vendor can hold one. We operate as a business associate under signed Business Associate Agreements. We also make no Safe Harbor or Expert Determination claim about any data.
- End-to-end encryption. tebIQ does not provide end-to-end encryption and we will not describe it that way: the server decrypts clinical text in order to generate a note. Our separate on-device dictation product is the only place that claim applies.
Security questionnaires and reviews
Send questionnaires, BAA requests, architecture-review requests, and vendor-risk paperwork to security@tebscribe.com. We answer from the audit evidence behind this page and we will tell you when the honest answer is “not yet”.
Vulnerability reports: /.well-known/security.txt (RFC 9116) or the same address.
Controls verified 11 August 2026. This page is re-verified before it is changed.
Charts done before you leave the building.
tebIQ is physician-built AI documentation. Try it free — no demo call, no sales rep.
Start free