Skip to main content

Security Model

Encryption at Rest

All secrets are encrypted with AES-256-GCM before being written to the database. The encryption key is never stored in the database itself. Decryption happens only at the point of use -- secrets are not cached in memory after decryption.

Ciphertext format: arcan:v1:AES256GCM:<base64-ciphertext>

Key Hierarchy

Master Key (stored in KMS or local file)

├── HKDF("arcan-dek-v1")
│ └── Data Encryption Key (DEK) — encrypts secrets at rest

├── HKDF("arcan-audit-hmac-v1")
│ └── Audit HMAC Key — integrity chain for audit log entries

├── HKDF("arcan-plugin-auth-v1")
│ └── Plugin Auth Key — authenticates plugin runtime sessions

└── Separate: Registry Signing Keys (Ed25519, not derived from master key)
├── Official key — public key embedded in core binary
└── Enterprise key — distributed with activation

All derived keys use HKDF-SHA256 (RFC 5869) with distinct info strings. Compromising one derived key does not compromise others. Rotating the master key rotates all derived keys.

Master key rules:

  • Never stored on disk in plaintext in production (KMS reference only)
  • Stored as []byte, zeroized after use -- never string
  • Standalone mode: auto-generated file at ~/.arcan/data/master.key (0600 permissions) or KMS
  • Multi-node mode: KMS required (sharing a file-based key across nodes is a security risk)

TLS Everywhere

TLS is required in all deployment modes with no exceptions. On first startup, Arcan generates:

  1. An internal CA certificate (~/.arcan/data/ca/ca.crt)
  2. A server certificate signed by that CA (~/.arcan/data/tls/server.crt)

Multi-node deployments can optionally enable mTLS for node-to-node communication.

Plugin Signing

All plugin packages (.arcanpkg) are verified with Ed25519 signatures before loading. The verification flow:

  1. Download package from registry
  2. Verify SHA-256 checksum
  3. Verify Ed25519 signature against the registry's public key
  4. Load into sandboxed runtime

Unsigned or tampered packages are rejected. The official signing key is embedded in the core binary. Enterprise packages use a separate key distributed with the activation license.

RBAC

Three built-in roles, scoped per realm:

RoleCapabilities
adminsecrets:read, secrets:write, secrets:delete, realms:manage, policy:manage, audit:read, tokens:manage
membersecrets:read, secrets:write, audit:read
viewersecrets:read, audit:read

The realm owner (creator) is automatically treated as admin. Policy middleware evaluates permissions on every request.

Threat Model

Attack SurfaceThreatMitigation
API endpointsUnauthorized accessAuth middleware on all routes except /api/v1/health
API endpointsBrute forceRate limiting per token and per IP
Master keyExtraction from memoryStored as []byte, zeroized after use; envelope encryption via KMS
Master keyExtraction from diskKMS reference only; file key uses 0600 permissions
Plugin packageSupply chain attackEd25519 signature verification before loading
Plugin packageTampering after downloadSHA-256 checksum on every load
Plugin runtimeNetwork/filesystem accessSandboxed -- plugins can only call declared host functions
Plugin runtimeCross-plugin data accessStore scoping by engine_id + realm_id
Plugin runtimePrivilege escalationCapability model -- core grants only declared capabilities
Stored secretsDatabase compromiseAES-256-GCM encryption; key never in DB
Stored secretsMemory dumpDecrypted only at point of use, not cached
Audit logTamperingAppend-only table, optional HMAC chain, SIEM export
API in transitMan-in-the-middleTLS required in all modes; mTLS option for multi-node
CLI credentialsToken theftToken file with 0600 permissions; token expiry
Config fileCredential leakageNo plaintext secrets -- env vars or KMS references only