Sophon 2.0 is here
Sophon Docs
Security

Credential Vault

How Sophon stores service credentials encrypted at rest and keeps them out of the model's prompt.

Sophon needs tokens for dozens of services — Gmail, GitHub, Slack, cloud providers — but the LLM driving your agent should never have one in its context. The credential vault stores every credential encrypted at rest, and the runtime resolves it at call time so the token is used at the network boundary rather than written into the prompt.

This is the same default-safe posture as Approval Gates: the model proposes an action, the runtime supplies the authority.

Where credentials live

Credentials live inside your data directory under ~/.sophon, written by the local vault backend. Each credential is serialized to JSON, encrypted, and stored as a single .vault file in ~/.sophon/vault/. The storage key is scoped per user as {userId}_{serviceId}, which is how multi-tenant deployments keep one user's tokens strictly isolated from another's.

A stored credential can hold an access token, a refresh token, a static API key, an expiry timestamp, and a bag of service-specific extra fields. OAuth-connected services also keep their refresh token here so the runtime can renew expired access tokens automatically.

The vault backend is pluggable via the Sophon:Vault:Provider setting (local, hashicorp, aws, or azure). The local provider is the default and is what Personal-tier installs use.

Encryption at rest

The local backend never writes plaintext. It picks a key protector per platform:

PlatformMechanism
WindowsDPAPI, scoped to CurrentUser — tied to your Windows account
Other OSesAES-256-CBC with a random 256-bit key persisted at ~/.sophon/security/vault.key (owner read/write only)

On Windows the encryption is bound to your OS user account, so the ciphertext cannot be decrypted by another account or on another machine. On non-Windows platforms the AES key in security/vault.key is what protects the data — it sits in the same data directory as the ciphertext, it is included in backups, and without it the encrypted credentials cannot be recovered.

There is no AEAD mode, no OS keyring integration, and no HSM or KMS on the local backend. For a production deployment off Windows, configure an external vault backend (HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault) rather than relying on the key file. Native Keychain and libsecret support for the local key is tracked as R-06 in the threat model roadmap.

Never paste an API key, token, or password directly into a chat message. Anything you type into a conversation becomes part of the LLM context — exactly what the vault exists to avoid. Always add credentials through Connections (Dashboard, sophon connect, or the API) so they go straight into the encrypted vault.

How a tool reaches a credential

There are two tiers, and they are not equally isolated.

Built-in tools run in-process. When one needs to call an external service, the runtime — not the LLM — fetches the token from the vault, makes the API call outside the model context, and returns only the sanitized result back to the agent. The token is never written into the prompt or the conversation.

Sandboxed skills declare what they need in the skill's manifest.json:

"credentials": [
  { "service": "google-calendar", "scopes": ["calendar.readonly"], "access": "injected" }
]

Three values of access are accepted:

  • "injected" — the default, and the spelling to use. The stored credential is placed into the skill's sandbox for the duration of one execution, and the container is destroyed afterwards. The skill code holds the credential while it runs.
  • "proxy" — deprecated alias of "injected". It delivers the credential identically, and is logged so the deprecation has a worklist. It is not an isolation boundary, and what arrives is the stored credential, not a short-lived scoped token. Older manifests that declare it keep working; new ones should say "injected".
  • "none" — declared so the Skills page can show a connection status badge. Nothing is delivered.

A sandboxed skill that declares a credential sees that credential. Keeping it out of the model's prompt is a real property; keeping it out of the skill is not. Install skills you trust, keep connection scopes minimal, and rely on the sandbox network allowlist — a skill with no declared egress has nowhere to send a token. A brokered proxy, where the sandbox returns an API-call instruction and the runtime makes the call outside it, is on the roadmap and not shipped.

Connection scopes

Scopes are bound at connect time, not at call time. When you start an OAuth connection, Sophon uses the scopes you request, falling back to the service's default scopes if none are given. The resulting token therefore carries only the permissions you granted — which is why scope minimization at connect time, not the access mode in a manifest, is what actually limits a skill.

Connection lifecycle — connect, test, refresh, revoke — is managed through the connection service and surfaced identically across the Dashboard, the sophon connect CLI, and the REST API. See Connections for the full setup walkthrough and the list of supported services.

What this guarantees

  • The LLM prompt and context window never contain a raw token.
  • Credentials are encrypted on disk: DPAPI-bound to your account on Windows, AES-256-CBC under a local key file elsewhere.
  • In multi-tenant mode, each user's credentials are isolated by vault key scoping.
  • A workflow step that calls a skill is flagged in the builder when a credential that skill requires is not connected, and the Skills page shows each declared credential's real connection status.
  • Every credential access can be recorded in the audit trail.

What it does not

  • It does not keep a credential away from a sandboxed skill that declared it.
  • It does not mint short-lived or per-call scoped tokens. What is delivered is what is stored.
  • On macOS and Linux it does not use the OS keyring (R-06).

For the broader hardening picture — approvals, sandboxing, and desktop control — see the Security Overview and the Threat Model.