# Credentials

Gives a workload in a smolvm machine an API key or token it can use but never read, by...

- Repository: https://github.com/smol-machines/smolvm (6894 stars)
- Category: Data and ML
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: yes, review before use

## Install

Claude Code: `npx skills add smol-machines/smolvm --skill credentials -g -a claude-code -y`
Codex: `npx skills add smol-machines/smolvm --skill credentials -g -a codex -y`
Cursor: `npx skills add smol-machines/smolvm --skill credentials -g -a cursor -y`
Gemini CLI: `npx skills add smol-machines/smolvm --skill credentials -g -a gemini-cli -y`

## Description

Gives a workload in a smolvm machine an API key or token it can use but never read, by binding the credential to named HTTPS hosts so the guest holds only a placeholder and the host substitutes the value on the way out, then proves on the host that the value never entered the machine. Use when an agent or untrusted code inside a machine has to call an API with your key; when deciding between a credential binding and --secret-env; when a request from a credentialed machine comes back 403 or 502 from smolvm itself; or when you need evidence that a key stayed out of a machine. Do not use it for a value the program must read and parse, such as a database URL, which is --secret-env, or for git and ssh keys, which is SSH agent forwarding.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# A credential the machine can use and never hold

Verified on **smolvm v1.29.0** on macOS arm64, 2026-10-15, and on **v1.18.2** on Linux aarch64, 2026-09-24, for everything that
is decided on the host; on v1.29.0 on macOS arm64 **the substituted value also arrived at a real API**
that echoes the headers it received, a dummy value. Done means the guest's variable is a placeholder, the value
is nowhere in the guest, the machine's record or smolvm's database, TLS to the bound host goes
through the machine's own CA, and a placeholder anywhere but a request header is refused before it
leaves the host (from v1.27.0 a binding with `:body` also substitutes into a form body).
The Linux runs used the scripts of their date; this version's preflight and cleanup scripts ran
on Linux aarch64 on v1.22.2 on 2026-10-03.

`docs/credential-substitution.md` in the smolvm repository is how the feature works: bindings,
where the value comes from, what the guest sees, what happens to each request, and the limits.
`README.md` has what was measured beside it. This file is how to set it up and prove it.

## Procedure

```
- [ ] 1. preflight.sh             the flag, the network backend, the host variable
- [ ] 2. create-credentialed.sh   a machine bound to one host
- [ ] 3. verify-containment.sh    the value stays out; the interceptor is on the path
- [ ] 4. your own request         the first call that sends the value
- [ ] 5. cleanup.sh
```

**1. Preflight.** Read-only, and it never prints the value or its length.

```bash
export API_TOKEN=...          # however your secrets manager hands it over
scripts/preflight.sh --var API_TOKEN --host api.example.com
```

Every script here reads the value from its own environment, so keep it exported in the shell that
runs `create-credentialed.sh` and `verify-containment.sh` as well as this one.

```
has_credential_flag=yes
default_backend=virtio-net
tsi_stream_intercept=yes
host_var_set=yes
host_form=ok
memory_required_mib=1024
result=ready
```

The rest: https://github.com/smol-machines/smolvm/blob/HEAD/docs/credentials/SKILL.md
