declaw:vault-managed.
This is the stronger sibling of Environment Secrets. With env secrets, the value is present in the VM (just masked in audit logs and excluded from get_info()) — any process inside the sandbox can read it from its environment. With the vault, the value is never delivered to the VM at all: a compromised agent that dumps /proc, reads the environment, or exfiltrates the process table sees only the placeholder. The credential is resolved and applied at the proxy layer between the VM and the upstream service.
Secrets are stored and referenced by name — there is no team or environment to set up. The value is written to the vault backend (OpenBao) and is never returned by any API after creation.
Using a vault secret in a sandbox
Pass a map of env var name → secret name at sandbox create time.demo-token looks up the secret named demo-token. The --vault-ref CLI flag is repeatable.
What the agent sees
The env var inside the VM holds the placeholder — never the real value:bearer injection sets the Authorization header). The agent issues a plain request; the proxy attaches the header before forwarding:
Storing a secret
A secret stores a value plus one or more scopes that tell the egress proxy which destination host the value is for and how to inject it. There are two ways to supply the scopes. The value is write-only: it is written to OpenBao and is never returned by any API after creation — not by create, list, or get.The vault is a cloud-mode feature and requires an authenticated API key. All operations are scoped to your account.
(a) From a provider preset
Name a built-in provider withprovider= and the preset supplies the domain regex, injection type, and any required static headers — you only paste the value. The secret name defaults to the provider key when omitted. Browse the catalog with list_presets / declaw vault presets.
(b) With explicit scopes
For a custom destination, provide the scopes yourself.domain_regex uses the vault’s ~ prefix to mark a case-insensitive regex match against the request host. The proxy anchors every scope automatically (wrapping it as ^(?:…)$), so a pattern like api.example.com matches that host only and never an attacker-suffixed look-alike (api.example.com.evil.com) — you may still write explicit ^…$ anchors, but you no longer have to. injection_type defaults to bearer; an optional rotation_interval_days enables a rotation policy.
List, rotate, and delete secrets
list returns metadata only (id, name, scopes, rotation status) — never the value. rotate replaces the stored value while leaving the scopes unchanged. Running sandboxes pick up the rotated value on their next outbound request (a short-lived TTL cache at the proxy) — no sandbox restart is required. delete removes both the metadata and the stored value.
A secret with
rotation_interval_days > 0 is flagged rotation_due in list output once that many days pass since it was last rotated (or created). This is an advisory signal — rotation is not automatic; call rotate to clear it.Update a secret’s scopes
update_scopes replaces a secret’s injection scopes in place — point it at a new destination or change the injection format — without re-supplying the value. It’s the in-place alternative to delete-and-recreate; running sandboxes pick up the new scopes on their next outbound request.
Injection types
A secret’s scope declares how the proxy presents it to the allowed destination. HTTP types inject into the TLS-intercepted request; socket types complete an authentication handshake transparently so the agent connects with no password.| Type | Transport | What it does |
|---|---|---|
bearer | HTTP | Authorization: Bearer <value> |
header | HTTP | <header_name>: <value> (with optional value_prefix scheme word) |
basic | HTTP | Authorization: Basic <value> (or base64(username:value) via basic_username) |
query | HTTP | Inject the value as a URL query parameter (header_name names the param) |
sigv4 | HTTP | Re-sign the request with AWS SigV4 (stored keys or STS federation) |
oidc | HTTP | Mint a short-lived OAuth2/OIDC bearer (client_credentials, token-exchange, discovery) |
hmac | HTTP | Sign the request with a configurable HMAC template (GitHub / Stripe / Slack styles) |
redis | Socket | Redis AUTH brokering |
postgres | Socket | Postgres auth brokering (cleartext / MD5 / SCRAM-SHA-256) |
mysql | Socket | MySQL auth brokering (native + caching_sha2, incl. RSA full-auth) |
smtp | Socket | SMTP AUTH brokering (AUTH PLAIN, STARTTLS) |
mongodb | Socket | MongoDB SCRAM-SHA-256 brokering |
Scope fields
A scope is one per-destination injection rule on a secret. The proxy matches a request’s host againstdomain_regex and injects the value per injection_type. All of the static fields below are applied at the egress proxy after the security scan, so they never appear in the request the agent issued — they let one scope express a provider’s full contract (e.g. Anthropic’s required anthropic-version header) without a new injection mechanism.
| Field | Required | Description |
|---|---|---|
domain_regex | Yes | Host match. Use the ~ prefix for a case-insensitive regex; the proxy anchors it automatically (^(?:…)$) so it cannot over-match a suffixed host. The value is only injected on requests to a matching host. |
injection_type | Defaults to bearer | How the value is presented: bearer, header, basic, query, plus brokered forms sigv4, oidc, hmac, and socket forms redis, postgres, mysql, smtp, mongodb. |
header_name | For header / query | Header name (e.g. X-Api-Key); for query it is the URL parameter name. Defaults to Authorization for the header type. |
value_prefix | No | Prepended verbatim to the value for the header type, so a scheme word can be emitted — e.g. "Token " → Authorization: Token <key>. |
basic_username | No | For the basic type: the proxy emits base64(username:value), letting you store a raw key instead of a pre-encoded credential. |
extra_headers | No | Static, non-secret headers set alongside the credential (e.g. Anthropic’s required anthropic-version: 2023-06-01). |
query_params | No | Static, non-secret query parameters added to the request URL. For a secret in the query string, use injection_type: "query" instead. |
Provider presets
Declaw ships a built-in catalog of ~39 first-party provider templates (OpenAI, Anthropic, Gemini, Bedrock, Cohere, Mistral, Hugging Face, Pinecone, LangSmith, ElevenLabs, Tavily, and more) so you can store a credential by naming the provider and pasting the value — no hand-written domain regex or header (see Storing a secret). The preset expands server-side into the correct scopes at create time; the worker only ever sees the resulting injection specs. Browse the live catalog:BYO secret-store connectors
A secret can hold a connector descriptor instead of a literal value — a pointer to your existing secret store. At injection time the worker fetches the real value from that store (cached, per the revocation TTL), so an upstream rotation is picked up automatically on the next cache miss. Implemented connectors:aws_sm · aws_ssm · gcp_sm · azure_kv · vault / openbao · infisical · doppler · k8s · 1password (Connect) · conjur · akeyless
The descriptor names the provider and the path to the value; the literal credential never lives in declaw.
Secret values live in OpenBao, never in declaw’s Postgres. The control plane stores only metadata — the secret’s id, name, scopes, and rotation status. The value is written to the vault backend and is fetched worker-side and injected at the proxy. It never enters the control-plane database and is never returned by the API after creation.
Trust boundary and the cert-pinned limitation. Vault HTTP injection rides declaw’s TLS interception at the egress proxy — the same edge proxy used for PII and injection scanning (see Network Policies). The proxy terminates TLS, attaches the credential, and re-originates to the upstream. This means an upstream that certificate-pins (rejects the proxy’s CA) cannot have a credential injected, because the proxy can’t sit in the TLS path. For socket brokers, the agent↔proxy leg is always cleartext within the sandbox’s own network namespace (where the proxy is the only gateway); the proxy↔upstream leg can opt into TLS (set
tls: true in the secret value) — smtp upgrades via STARTTLS, redis and mongodb negotiate TLS at connect time, and postgres and mysql upgrade in-protocol — so a database that mandates TLS on the wire is brokered too.