Security Model
How varsafe stores, transmits, and controls access to your secrets — stated precisely, including what varsafe does not do.
This page describes varsafe’s security architecture as it is actually built. Every claim here is scoped: where a protection has limits, the limits are stated.
Security Architecture Overview
Every request follows the same path:
- TLS — all connections are encrypted in transit
- Validate — the session token or API token is hashed and verified
- Authorize — role and environment permissions are checked in the application layer
- Store — secret references and metadata go to the database; secret values go to the vault
Secrets Storage
Where Secret Values Live
Secret values are stored in a dedicated secrets vault (Scaleway Secret Manager), encrypted at rest with KMS-managed keys. The application database stores references only — a pointer to the vault entry, never the value:
In the database:
- Secret keys (names, not values)
- Vault references and version numbers
- Timestamps and team/project/environment relationships
- Audit events
In the vault:
- The actual secret values, versioned
The Access Model, Honestly
varsafe is a server-side secrets manager, not an end-to-end encrypted system. The varsafe API decrypts secret values in order to serve authorized requests — that is what makes varsafe run work. What protects your secrets is layered access control, not client-held keys:
- Vault access is restricted to the varsafe API
- Every read is authenticated, authorized against your role, and audited
- Values are encrypted at rest (vault + KMS) and in transit (TLS)
The same applies to encrypted .env files: each environment has an X25519 keypair, and the server manages the environment keys — private keys are stored server-side, encrypted by KMS. Encrypted .env files protect the file at rest and in transit, so they can be committed. Getting the private key needed to read one is authorized by the varsafe API and restricted to an interactive owner or admin session — but be clear about what that means: once the API hands the key over, the holder can decrypt every file sealed under it, offline, for as long as they keep it. Treat a private-key export as granting durable read access to that environment, and rotate the underlying secrets — not just the key — if it lands somewhere it should not have.
Cross-System Write Safety
Secret writes span two systems (the vault and the database). varsafe records each operation in a durable write-ahead log before touching either system, so a crash mid-operation is detected and recovered rather than leaving the vault and database silently inconsistent.
run vs export
varsafe runinjects secrets directly into the child process environment. Nothing is written to disk.varsafe exportwrites a file — deliberately, at your request. Env-format exports are encrypted by default; plaintext requires the explicit--plainflag.
Authentication
Session Tokens
varsafe uses opaque session tokens:
- Generation — cryptographically secure random bytes
- Storage — tokens are hashed before storage; a database leak does not expose usable sessions
- Lifetime — sessions expire 7 days after their last renewal, with rolling renewal on activity (at most hourly). A stolen idle cookie dies within a week of its last legitimate use.
- Cookies —
HttpOnly,Secure(in production),SameSite=Lax
API Tokens
API tokens (vs_at_ prefix) are stored as salted hashes, always carry an expiration, and can be scoped to specific projects and environments. See API Tokens.
Multi-Factor Authentication
TOTP (Time-based One-Time Password):
- Standard TOTP algorithm (RFC 6238)
- Works with Google Authenticator, Authy, 1Password, etc.
- Single-use backup codes for recovery
Passkeys (WebAuthn):
- Biometric authentication (Touch ID, Face ID) or hardware security keys
- Phishing-resistant — credentials are bound to the varsafe domain
- Passkey-only mode disables password login entirely (requires at least 2 registered passkeys)
Device Trust:
- Email/password logins from unrecognized devices require a one-time email code
- Verified devices are remembered; passkey and OAuth logins skip the check (already device-bound)
- Manage trusted devices from Profile → Security
See Authentication for setup procedures.
Authorization
Authorization is enforced in the application layer on every request: the actor’s team membership and role are checked against the resource’s team, project, and environment.
Role-Based Access Control
Six roles (owner, admin, developer, operator, viewer, billing) control secret access, team management, and billing. Protected environments further restrict writes to owners and admins. The full matrix lives in Roles & Permissions.
By default, production is marked as protected in new projects. Any environment can be protected via its settings.
API Token Authorization
API tokens are scoped to a single team, optionally narrowed to specific projects and environments — scoping is enforced server-side on every request. Tokens have their own audit identity.
Data Isolation
Multi-Tenant Architecture
varsafe isolates teams with two independent layers:
- Application-layer scoping — every query is scoped to the teams the actor belongs to; ownership is checked before any read or write
- PostgreSQL row-level security (RLS) — high-risk tables (secret references, environment keypairs, API tokens, and others) additionally carry database-enforced RLS policies keyed to the request’s team, so even a defective query cannot cross tenant boundaries
Secret values in the vault are namespaced per team.
Namespace Structure
Audit Trail
Every security-relevant action is logged with actor, target, team, IP address, and user agent.
Audit Properties
- Append-only — the application only ever inserts audit events; there is no API to modify or delete them
- Complete — every secret access, export, and mutation is logged, including access by API tokens
- Retention-bounded — events are retained per plan (7 days on Developer, 90 days on Team) and pruned after the window; export regularly if you need a longer archive
- Exportable — CSV export from the dashboard, plus structured JSON exports formatted for SOC 2, GDPR Article 30, and HIPAA reviews (Team plan)
Composed secrets disclose their whole closure
Reading one composed secret reveals the value of every secret it embeds, so the audit event records
the full closure — reading DATABASE_URL is logged as access to DATABASE_URL, DB_USER and
DB_PASS, not just the key requested. A compromise review that saw only the requested key would
clear a credential that in fact leaked.
Two consequences worth planning around:
- Granting read access to a composed secret grants read access to its inputs, in effect. There is no way to read the resolved value without learning what it was built from. Composition does not narrow disclosure; it narrows duplication.
- A composed read’s closure is always recorded in full. One secret may resolve against at most
64 others, which is deliberately below the 200-name cap on a single audit event — so the names of
every credential a composed read disclosed are retained, not truncated. Exceeding that bound is
refused at resolution time rather than logged incompletely. (Whole-environment exports of more
than 200 secrets still record a
keysTruncatedflag with an exact total; that is a bulk read where the caller asked for everything.)
References never cross an environment, project, or team boundary, so a composed secret’s closure is always inside the tenant the reader was already authorized for.
See Operations for the event catalog and export procedures.
Network Security
TLS
All connections — dashboard, CLI, and API — use TLS.
Rate Limiting
Authentication endpoints have dedicated per-IP limits:
| Endpoint | Limit |
|---|---|
| Sign-in | 10 per minute |
| Sign-up | 10 per minute |
| Forgot password | 5 per 5 minutes |
| Two-factor verify | 10 per minute |
| Other auth routes | 100 per minute |
General API traffic is throttled across three windows (per second, per 10 seconds, per minute — 10/50/200 for unauthenticated traffic). Authenticated users receive a 5x multiplier.
Incident Response
Compromise Response
If a secret is compromised, act immediately:
- Rotate — use the rotation workflow to issue a new value
- Revoke — invalidate any leaked sessions or API tokens
- Audit — review the audit log for unauthorized access
- Report — document the incident for compliance
See Operations → Incident Response for the full runbooks.
Session Revocation
Sessions can be revoked:
- By the user (logout, or per-session from Active Sessions)
- On password change or reset (all sessions)
- Automatically (expiration)
Revocation is immediate — no waiting for token expiry.
Security Best Practices
For developers
- Never commit plaintext secrets — use
varsafe run, or encrypted exports when a file is unavoidable - Use passkeys — phishing-resistant, stronger than passwords
- Enable 2FA — protects password-based accounts
- Review audit logs — watch for anomalies
For admins
- Principle of least privilege — viewer or operator for most members, developer only where writes are needed
- Protect sensitive environments — protection restricts writes to owners and admins
- Regular access reviews — remove departed members; their key access triggers automatic keypair rotation
- Scope API tokens — one token per pipeline, narrowed to its project and environment
For security teams
- Export audit logs — feed CSV or JSON exports into your SIEM before the retention window prunes them
- Test incident response — simulate a compromised secret and a compromised token
- Review token inventory — expirations, scoping, last-used timestamps
Compliance
varsafe is designed to support common compliance programs — it is not a substitute for your own certification, and this page makes no certification claims.
| Framework | What varsafe provides |
|---|---|
| SOC 2 | Append-only audit trail, role-based access control, encryption at rest/in transit, access-review reports |
| GDPR | Audit export formatted for Article 30 processing records |
| HIPAA | Access controls, per-access audit logging, structured access export |
| PCI DSS | Centralized secrets management with access logging |
See Operations for export procedures.
Reporting Security Issues
Security vulnerabilities should be reported privately:
Contact form — select “Security Issue” in the dropdown.
Please do not discuss vulnerabilities publicly before they are resolved, and do not test against production systems without authorization. We aim to acknowledge reports within 24 hours and provide fixes within 90 days.