Built for the people who get audited.
Every control your procurement team is about to ask about. If you need a deeper artifact, request our security questionnaire response or current pen-test report under NDA.
TLS 1.3 in flight · AES-256 at rest
All HTTP traffic over TLS 1.3 with HSTS. Database AES-256 at rest. Per-org LLM keys and SAML IdP certificates encrypted with Fernet (AES-128-CBC + HMAC-SHA256) using a separate ENCRYPTION_KEY.
Row-level isolation, enforced in every query
Every record is scoped by org_id at the database layer. Every API query joins through the JWT-derived org. Vendor uniqueness is per-org. The only role that bypasses scoping is super_admin (operational use).
MFA · per-org SSO (OIDC + SAML) · RBAC
TOTP MFA with 10 hashed recovery codes. Per-org OIDC and SAML 2.0 with email-domain discovery. Four built-in roles (reviewer / attestor / org_admin / super_admin) plus configurable permission groups on Growth+.
SOC 2 Type II in progress · annual pen test
Type I gap assessment complete; Type II observation period underway. External penetration test on the production stack annually. Reports shared with Enterprise customers under NDA.
Detailed control posture
Identity & access
Authentication is bcrypt + HS256 JWT for local accounts, OIDC (authorization-code with PKCE) and SAML 2.0 for federated. Email-first discovery maps user domain to org auth methods.
- Bcrypt password hashing with per-user salt
- HS256-signed access tokens (15-minute expiry) + HttpOnly refresh cookie
- TOTP MFA via pyotp with 10 hashed single-use recovery codes
- Per-org OIDC with PKCE; JIT user creation with configurable default role
- Per-org SAML 2.0 with IdP certificate Fernet-encrypted at rest
- Org-required MFA toggle (Growth+); super_admin exempt to prevent platform lockout
- SSO-only mode optionally enforced; org_admin retains break-glass password
- Login rate limit: 5/minute per IP via slowapi
Session management
Every issued access token carries a unique jti. Sessions are tracked in active_sessions and can be revoked at two levels.
- Soft revoke (user): revokes refresh token; access dies at JWT expiry (≤15 min)
- Force logout (admin): revokes refresh + adds jti to Redis blocklist for immediate 401 on the next request
- Blocklist check runs on every authenticated request (~0.1 ms; degrades gracefully if Redis is down)
- last_active_at and current_jti updated on every refresh
- Session listing surfaces every active session per user with IP / user-agent
Data isolation & multi-tenancy
All customer data is org-scoped at the row level. Cross-tenant data leakage requires a router bug, not just an auth bypass.
- org_id column on users, vendors, evidence, audit logs (reports/reviews/attestations inherit via vendor FK)
- Every router query joins through the JWT-derived org
- Vendor uniqueness composite-keyed on (org_id, name)
- Per-org Anthropic / Gemini LLM keys, encrypted with Fernet
- Cross-org operations require super_admin (explicit, audited)
Application hardening
Defense-in-depth at the application layer beyond auth.
- TLS 1.3 + HSTS via Let's Encrypt (auto-renew daily via certbot.timer)
- Standard security headers: CSP, X-Frame-Options, X-Content-Type-Options
- PDF and DOCX uploads validated by magic bytes (not just MIME)
- File-size limits on uploads; rejected with explicit error
- Backend bound to 127.0.0.1; only nginx talks to it
- CORS allowlist controlled by ALLOWED_ORIGINS env (no wildcards)
- All mutating actions emit append-only audit-log events
Deployment models
Three deployment options reflect three trust postures. Choose the one your security team can defend.
- Cloud SaaS (default): multi-tenant on socbot.cyberblacksec.com, US-EAST hosting
- Private deploy: single-tenant either on our infrastructure or in your AWS / Azure / GCP VPC (+$18–24K/yr)
- On-prem / air-gapped: customer-hosted, full source escrow option (+$36K/yr including installation and first-year support)
- Self-host pattern uses Docker images; no public internet egress required in air-gap mode
Backup, disaster recovery, and verification
Two-layer backup with weekly automated restore verification. The verification is what auditors actually look for.
- Nightly local backup: pg_dump (gzip-9), uploads tarball, gpg-AES256 encrypted .env, SHA-256 manifest
- Off-host nightly push to Cloudflare R2 in a separate cloud account
- Weekly automated restore test: pulls latest dump from R2, restores into isolated DB, dynamically enumerates all tables, row-count parity vs live
- Restore script verifies SHA-256 manifest before touching the live DB
- Code archive weekly to R2 with .env / secrets / build artifacts excluded
- Retention: 14 days local, governed by R2 bucket lifecycle off-host
Audit logging
Every action that changes state writes an append-only audit event.
- Append-only audit_logs table with category (user / info / security / error / processing / ai) and severity
- All major mutating actions emit events: auth, user mgmt, report upload / analyze, evidence ops, reviews, attestations, annotation changes, OIDC / SAML config, sessions, vendor import
- Annotation activity feed tracks old → new value for every reviewer override
- Admin UI at /audit-logs with filters + pagination
- Audit data retention configurable on Enterprise (default 1 year)
LLM key posture (BYOK)
Every org configures its own Anthropic and Gemini API keys. We never proxy LLM calls through a shared key.
- Anthropic + Gemini keys stored Fernet-encrypted in organizations.settings
- Decrypted in-memory only at call time; never logged
- Prompt-cache locality: cache lives in the customer's Anthropic account, not ours
- Customer controls model selection, prompt-cache spend, and rate limits
- Key rotation is a one-screen settings change with no service interruption
- Air-gap deployments support local-model alternatives via Ollama (Enterprise add-on)
Who else touches the data
A complete list of third parties involved in processing customer data on Cloud SaaS. Private deploy and on-prem customers can remove most of these from the picture.
| Sub-processor | Role | Region | Scope of data |
|---|---|---|---|
| Anthropic (Claude API) | LLM provider for the 5-phase analysis pipeline | US | Customer keys (BYOK). Prompts include SOC report text + system prompts. Customer-owned account; we never see the prompts or responses. |
| Google (Gemini API) | Alternative LLM provider | US (global routing) | Customer keys (BYOK). Same posture as Anthropic — customer-owned account. |
| DigitalOcean | Primary cloud hosting (Cloud SaaS only) | US-EAST (NYC3 region) | Hosts the application server, PostgreSQL, Redis, and uploaded files for Cloud SaaS customers. Private deploy customers host their own. |
| Cloudflare R2 | Off-host encrypted backup storage | Auto (US-bound) | Encrypted database dumps, file backups, and the gpg-encrypted .env. Bucket lives in a separate cloud account from primary hosting. |
| Let's Encrypt | TLS certificate authority | Global | Issues and auto-renews TLS certs for the customer-facing domain. No customer data ever transits. |
| SendGrid / SMTP (configurable) | Transactional email delivery | Configured per-tenant | User invites, password resets, attestation notifications, audit-committee briefings. SMTP host is org-configurable; can be customer's own Microsoft 365 / Google Workspace. |
Procurement asking deeper questions?
We have a pre-filled response to the standard SIG / VSAQ / CAIQ questionnaires. Send your security team straight to us — we’ll turn it around in two business days.