Security overview
Verdict targets OWASP ASVS 4.0 level 2 for the API and console, with level 3 controls for keys, secrets and logging. This page is the customer view. Report a vulnerability by email to [email protected] with the subject SECURITY: <short summary>. Do not include live credentials. Acknowledgement within 2 business days.
API keys
Section titled “API keys”- 32 bytes from a cryptographic random generator, base62, prefixed
vd_live_orvd_test_. - Stored only as a SHA-256 hash with a server-side pepper. Shown once at creation. Never retrievable.
- Never logged: a redaction layer masks anything shaped like a key in logs, errors and traces.
- Scoped (see Concepts), with optional rate limit, IP allowlist, daily spend cap and expiry per key.
- Rotation issues a new key and keeps the old one valid for a grace window you choose (default 24 hours).
Sign-up and console
Section titled “Sign-up and console”- Email verification before any key is issued. Disposable email domains are refused. Sign-ups are rate limited per IP and per domain.
- Console sign-in by magic link (single use, 10-minute expiry) or GitHub. No passwords.
- Optional TOTP, required for org owners once an org has more than one member.
- Roles: owner, admin, developer, billing, read-only. Checked on the server for every action.
Transport and edge
Section titled “Transport and edge”- TLS 1.2 minimum, 1.3 preferred. HSTS preload. No plaintext listeners.
- Cloudflare in front of every public hostname: managed WAF rules, bot management, an edge rate limit above the per-key limits.
- The origin accepts traffic only through Cloudflare.
Input handling
Section titled “Input handling”- Every request body is validated against the published schema. Unknown fields are rejected.
- Size caps: 256 KB bodies, 50 roster entries, 40 thread messages, 8 KB per message.
- No SQL built from strings. No shell execution from request paths.
- Verdict fetches no URL you send, except webhook deliveries to endpoints you registered and verified.
Tenant isolation
Section titled “Tenant isolation”Every table that holds org data has Postgres row-level security, forced for the API’s database role. Each transaction sets the org from the authenticated key. An automated test asserts every org-scoped table has a policy and that a cross-org read returns zero rows.
Data you send
Section titled “Data you send”- Rosters, threads and ICP text are processed for the request and not stored, except in a 30-day request log where emails, phone numbers and names are redacted first.
- Decisions store feature hashes, probabilities and token counts, never your text.
- Decisions and outcomes are kept for the life of the org plus 90 days. Org deletion completes within 30 days and is confirmed by email.
- Verdict is a processor for the data you send and a controller for its index of public business data. See the DPA and privacy policy.
Model-input safety
Section titled “Model-input safety”Every text field that reaches the decision model (thread messages, event descriptions, your ICP text) passes an injection guard first. It neutralizes instruction-shaped content: role assertions, “ignore previous”, fake system text and non-evidence URLs. This keeps a hostile reply from steering your decision.
Webhooks
Section titled “Webhooks”- Watch deliveries are signed:
Verdict-Signature: t=<ts>,v1=<hmac-sha256>. Reject skew over 5 minutes. Secrets rotate with overlap. See Watches. - Registered URLs must be HTTPS and answer a challenge. Private and link-local IP ranges are refused.
- Inbound receivers verify each vendor’s signature before parsing and are idempotent on the vendor event id.
Secrets
Section titled “Secrets”All service secrets live in a secrets manager and are injected at runtime. Webhook secrets and phase-2 vendor keys are encrypted at rest with AES-256-GCM under per-row data keys wrapped by a master key, decrypted only in memory, never returned by any API, and every access is audit-logged.
Logging and audit
Section titled “Logging and audit”- Structured logs with request id, org, key id, route, status, latency and cost. Never bodies, keys or personal data. Kept 30 days.
- An append-only audit log of key, scope, member, threshold, webhook, top-up, export and deletion events, readable with
GET /v1/audit(scopeaccount:read). - Alerts on error rate, latency, decision-model errors, ingestion failures, ledger drift and abnormal spend per key.
Compliance
Section titled “Compliance”No SOC 2 report yet; the controls above are mapped to the Trust Services Criteria for readiness. A penetration test is commissioned before public launch and yearly after. Confirmed data incidents are notified to affected customers within 72 hours. Legal documents are on Legal; they are drafts until reviewed by counsel.