Security & trust
Security model
Least-privilege and read-only by design, first-party identity with mandatory MFA, hard per-tenant isolation, and a cryptographic audit spine you can verify yourself.
TrustFix is built so a security engineer can independently verify our claims rather than take them on faith. The model rests on least-privilege read-only access, first-party identity with mandatory MFA, hard per-tenant isolation, and a cryptographic audit spine.
Read-only, least-privilege access
TrustFix reads your estate through least-privilege, read-only connectors and never writes to your infrastructure during connection or scanning. Cloud connections favor short-lived federation over stored secrets:
- AWS — cross-account
sts:AssumeRolewith a server-derived External ID, which prevents confused-deputy attacks: only TrustFix, from its specific principal, can assume your role even if an attacker knows the ARN. The recommended template grants only the specific read actions needed and never reads secret, parameter, or object values. - GCP and Azure — Workload Identity Federation, so no long-lived service-account keys or client secrets are stored on either side.
Every scan uses fresh temporary credentials that expire automatically and are never written to disk or logged. TrustFix never stores cloud access keys or secret keys, and all fix recommendations are delivered as pull requests that require human review — there is no automated remediation that touches your infrastructure directly.
First-party identity with mandatory MFA
Authentication is first-party (TFID); the prior third-party IdP dependency has been removed. The principal is resolved from an opaque, database-validated session cookie at a single server chokepoint that fails closed — edge middleware only does a cheap cookie-presence and CSRF pre-check, never the authoritative decision.
- MFA is mandatory. A session that hasn't satisfied MFA is not a usable principal. TOTP and WebAuthn passkeys are supported; TOTP secrets are sealed at rest (AES-256-GCM), step-replay is rejected, recovery codes are single-use, and a passkey signature-counter regression (cloned-authenticator detection) is rejected. You cannot remove your last factor.
- SSO — per-tenant SAML 2.0 / OIDC with group-claim → role mapping and optional SSO-only enforcement, gated on the tenant's entitlement.
- Auth events are recorded durably, and identity-lifecycle and privilege events (access provisioned, role changed, account suspended) are additionally anchored in the Trust Ledger — hash-only, so no emails, roles, or secrets enter the ledger.
Role-based access control
Org membership uses four roles in a strict hierarchy — VIEWER < MEMBER < ADMIN < OWNER — and
every check resolves the role from the database, never from a session claim:
| Capability | OWNER | ADMIN | MEMBER | VIEWER |
|---|---|---|---|---|
| View findings, view team | ✓ | ✓ | ✓ | ✓ |
| Generate fix, create PR, run scan | ✓ | ✓ | ✓ | — |
| Connect AWS, install GitHub, invite members, manage roles, view audit log | ✓ | ✓ | — | — |
| Manage billing | ✓ | — | — | — |
The most sensitive actions are OWNER-only — member role changes (confirm-stepped and last-OWNER-protected) and SSO editing/enforcement. SSO and SOC 2 evidence export resolve per-tenant entitlements, and entitlements are strictly tenant-scoped — one tenant's never affects another's. Teams can scope a member to specific AWS accounts and repos; a member in no team sees nothing, and a team with no scopes acts as an all-access team.
Operator support uses a separate, time-boxed, read-only "View-As" path, available only to super-admins defined by an environment allowlist (no database flag, by design). The override is HMAC-signed, honored only on safe HTTP methods, entirely disabled when its signing secret is unset, and every entry and exit is audited and surfaced to the customer.
Per-tenant isolation by construction
Isolation is defense in depth across two independent layers:
- Manual org-scoping via an
orgScope()primitive used across the read paths. - A structural Prisma backstop: requests run inside a request-scoped tenant context, and a
query hook for tenant-resource models injects
organizationIdwhen omitted and rejects any query targeting a different org with a fail-closedCrossTenantQueryError.
The read org resolver (which honors read-only View-As) is separated from a write-safe resolver that never honors View-As, so a write on a GET transport (an OAuth callback, an export download) can never land in a View-As target tenant.
The cryptographic audit spine
Every consequential action is recorded in the per-tenant
Trust Ledger — append-only, hash-chained,
Ed25519-signed, with Merkle inclusion proofs. verifyChain recomputes every hash, link, and
signature, so any mutated, reordered, or forged row breaks it; an inclusion proof lets an
auditor re-verify a single action offline. Agent-passport revocation is published as a
signed Token Status List plus an agent CRL for O(1), herd-private, offline revocation checks.
Credential handling and data lifecycle
Any long-lived secret that must be held (OAuth tokens, PATs) is sealed with KMS envelope
encryption (AES-256-GCM) and bound to the organizationId as encryption-context AAD, so a
decrypt attempt against a different org fails at the KMS layer. API keys store only a SHA-256
hash — the plaintext token is shown exactly once. OAuth flows use PKCE. On offboarding or a
right-to-be-forgotten request, PII payloads are tombstoned while the signed ledger entries
are preserved and still chain-verify — proving a record existed without retaining the personal
data.