Secrets and credentials
Secrets are not ordinary configuration. A sandbox can print them, copy them, persist them in snapshots, or expose them through files and logs if the workflow is careless. Treat credential delivery as a policy decision with a reviewable grant.
Preferred model
Section titled “Preferred model”| Step | Rule |
|---|---|
| Store | Store a named secret reference with the local secret store. |
| Declare | Reference the secret by name in a manifest, declaration, or SDK request. |
| Grant | Bind the reference to a workload, command, or tool operation. |
| Deliver | Prefer host-mediated release paths over raw guest-visible values. |
| Redact | Scrub stdout, stderr, logs, errors, receipts, and model-facing results. |
| Retain | Treat snapshots, cold state, volumes, and copied files as secret-bearing until proven otherwise. |
The secure default is reference-first. Raw values should not appear in source files, examples, command history, model prompts, or long-lived logs.
CLI flow
Section titled “CLI flow”Store a named reference:
mvmctl secret put openai-api-keyDeclare the reference in a workload manifest or SDK declaration, then run under
the policy that grants that reference to the workload. Avoid passing secrets
through argv or --env; those paths are easy to leak through process listings,
shell history, debug output, and crash reports.
SDK declarations
Section titled “SDK declarations”env={ "OPENAI_API_KEY": mvm.secret("openai-api-key", var="OPENAI_API_KEY"),}env: { OPENAI_API_KEY: mvm.secret("openai-api-key", { var: "OPENAI_API_KEY" }),}The declaration records the reference. It should not contain the credential value.
Runtime SDK target
Section titled “Runtime SDK target”The runtime SDK target should preserve the same shape:
from mvm import Sandbox, SecretRef
with Sandbox.create( image="nix:./flake#agent-runtime", secrets={"OPENAI_API_KEY": SecretRef("openai-api-key")},) as sandbox: sandbox.commands.run(["python", "/work/tool.py"], timeout_seconds=30)import { Sandbox, SecretRef } from "@mvm/sdk";
using sandbox = await Sandbox.create({ image: "nix:./flake#agent-runtime", secrets: { OPENAI_API_KEY: SecretRef.from("openai-api-key") },});
await sandbox.commands.run(["node", "/work/tool.js"], { timeoutSeconds: 30,});Check Operations cookbook and Lifecycle matrix before treating a helper as shipped in a language SDK.
File-mounted secrets
Section titled “File-mounted secrets”Some workloads still need file-shaped secrets, certificates, or config bundles. When using a secrets drive:
- mount the narrowest directory possible;
- keep files read-only inside the guest;
- use non-secret test data in docs and fixtures;
- do not share the same mounted directory across unrelated workloads;
- treat snapshots and cold state as secret-bearing after the mount has been visible to a guest;
- remove or rotate credentials after a workflow that allowed generated code to read them.
Prefer managed secret references for credentials. Use file mounts for formats that cannot reasonably be expressed as references.
Agent and model workflows
Section titled “Agent and model workflows”Models should never invent secret names or values. The application should map a tool capability to an allowed reference:
{ "tool": "web_fetch", "secrets": { "OPENAI_API_KEY": { "ref": "openai-api-key" } }}Rules for model-facing tools:
- grant secrets per operation;
- never echo resolved values to the model;
- redact command output before it becomes model context;
- reject requests that ask to print, exfiltrate, or persist credentials;
- record the grant decision with the audit/run identifier.
Redaction and failure handling
Section titled “Redaction and failure handling”Every secret-bearing path should have a failure behavior:
| Path | Failure behavior |
|---|---|
| Missing reference | Fail closed before VM launch or command execution. |
| Unauthorized reference | Return policy denial, not a generic runtime failure. |
| Guest prints a secret | Redact before logs or model-facing responses leave the app. |
| Cleanup fails | Report cleanup failure separately and mark retained state as sensitive. |
| Snapshot retained | Attach retention metadata and delete or rotate when no longer needed. |
Do not collapse secret failures into generic command errors. Operators need to know whether a workload failed because of policy, missing credentials, guest behavior, or cleanup.