Skip to main content

Principles

1

No plaintext at rest

Credentials are always encrypted in the database — XChaCha20-Poly1305 for zero-knowledge items, AES-256-GCM for server-managed items.
2

No decrypt before auth

Authentication, permission, expiry, locality, and storage-mode checks all run before any decryption.
3

No implicit access

Every agent–credential pair requires an explicit permission row. There are no wildcards, no roles, no inheritance.
4

No silent access

Every attempt — allowed, denied, expired, revoked — is appended to the audit log before the response is returned.
5

No secret exposure to LLMs

MCP tools inject secrets into subprocesses, never into model context.

Encryption modes

abadge supports two storage modes with distinct trust models.
The server never sees plaintext. All cryptographic operations happen in the browser or the local CLI daemon.The server stores: wrapped root key, KDF salt + parameters, wrapped DEKs, and ciphertext. None of these is enough to decrypt without the master password (or recovery key).Recovery: a 256-bit recovery key (base32, shown once) independently wraps the root key. There is no server-side recovery.See Zero-knowledge encryption for the full hierarchy.

Comparison

Authentication

Human operators

The CLI never persists a human bearer token to disk.

Agents

Agents authenticate with Ed25519 public-key sessions — the only agent auth method. The agent generates an Ed25519 keypair locally; the server stores only the public key. For each session: POST /v1/agents/{agentId}/sessions/challenge → sign → POST /v1/agents/{agentId}/sessions/exchange → receive abs_... token (15-minute TTL). The SDK refreshes at T-2 minutes. The abs_... session token is the only credential that reaches the access.* surface. Personal API keys (management surface). Users can mint personal API keys (abu_) from the dashboard org Settings page to script the management surface without a browser. An abu_ key resolves to a session identity, not an agent: it reaches only the management surface (organizations, profiles, items metadata, agents, permissions, audit, settings) and is structurally barred from access.* — it can never read a secret as an agent, and can never decrypt a zero_knowledge item (the server never holds the key). Like any account owner, it can owner-reveal its own server_managed plaintext via items.ownerReveal (the server holds those keys by design). The server stores a SHA-256 hash + 8-char prefix; the secret is shown once. Keys support an optional expiry and can be revoked. Bearer resolution order on every request:
  1. Session cookie / bearer token → operator session (management surface)
  2. abu_ prefix → personal API key (prefix lookup, hash match) → session identity, management surface only
  3. abs_ prefix → agent session token (hash lookup, TTL check) → agent identity (the only path to access.*)

Authorization

Access requires an explicit (agent, item, capability) permission row. There are no wildcards, no role-based inheritance, and no implicit grants. The full decision flow is in Permissions and capabilities.

Delivery modes

use with delivery: env. The CLI or daemon spawns a subprocess with the secret in an env var. The secret lives only in process memory; the parent process drops the value after spawn.

Network security

Credential handling on disk

Server breach impact

ZK items remain protected after a full server breach, assuming a strong master password. Server-managed items are exposed if the attacker also obtains the Worker’s ENCRYPTION_KEY.

Stored data summary

Explicit non-goals (v1)

These are not protected against:
  • Local root/admin attackers reading process memory
  • HSM or hardware-key integration
  • Secure multi-party computation for shared secrets
  • Tamper-evident audit log chaining
  • Compromised build/deploy pipelines serving malicious JS
  • Organization-level vault cryptography (each profile has its own root)