Workflows secrets overview
Keep credentials out of your workflow YAML. The secrets keyword declares sensitive runtime values per job — Loom resolves provider-backed references at execution time, injects values as file paths by default, and redacts them from all output.
For the conceptual model and security background, see:
- Secrets concept — why references instead of values
- Secrets overview — full configuration reference
- Secrets security — threat model and controls
YAML shape
Add a secrets block to any job. Each key becomes an environment variable in the job's execution environment.
deploy:
stage: ci
target: linux
secrets:
DATABASE_PASSWORD:
ref: keepass://local/main#services/loom/deploy:password
file: true
required: true
API_TOKEN:
ref: op://Engineering/services/loom/deploy/token
file: false
required: false
script:
- ./scripts/deploy.sh
secrets is valid only on job blocks — not in default. This prevents a single declaration from fanning sensitive material to every job in the workflow.
Secret spec fields
| Field | Required | Default | Description |
|---|---|---|---|
ref | Yes | — | Provider URI that identifies the secret value. The URI scheme determines which provider resolves it. |
file | No | true | true: Loom writes the value to a 0600 temp file and sets the env var to the file path. false: the raw value is placed directly in the env var. |
required | No | true | true: the job fails if the secret cannot be resolved. false: the env var is omitted and the job continues. |
Supported URI schemes
| Scheme | Format | When to use |
|---|---|---|
env:// | env://<VAR_NAME> | Value is already in the host environment (CI runner injects it, or exported in the shell). No vault setup required. |
keepass:// | keepass://<database-alias>#<entry-path>:<field> | Local or offline encrypted vault. No external service dependency. |
op:// | op://<vault>/<item-path>/<field> | Centralized team vaults with access control and audit logging. Resolved via the 1Password Go SDK — no op CLI needed. |
All three schemes are implemented and production-ready. Providers fail closed — if auth or config is missing, resolution produces a deterministic SECRETS_* error code rather than a silent fallback.
Choosing a provider
| Consideration | env:// | keepass:// | op:// |
|---|---|---|---|
| Setup effort | Minimal — export a variable | Moderate — create .kdbx, configure alias env vars | Moderate — create service account, export token |
| Offline support | Yes | Yes | No (requires network) |
| Team sharing | Manual (CI runner config) | Manual (distribute .kdbx + credentials) | Built-in (vault access control) |
| Audit trail | None | None | 1Password audit log |
| Best for | Quick prototyping, CI-managed secrets | Solo/local dev, air-gapped environments | Teams, production workflows |
Use env:// to get started fast. Graduate to keepass:// or op:// when you need structured secret management or team-wide access.
Injection modes
| Mode | file value | Job sees | Use case |
|---|---|---|---|
| File injection (default) | true | Path to a 0600 temp file | Most cases — lower leakage risk from shell tracing, ps, and interpolation |
| Direct injection | false | Raw secret value | Only when a tool requires a direct env value and cannot read from a file |
File-injected secrets are read in scripts with cat:
DB_PASS=$(cat "$DATABASE_PASSWORD")
For Docker jobs, file-injected secrets are bind-mounted read-only into the container. Scripts inside the container use the same cat "$VAR" pattern.
Validation and guardrails
| Rule | Enforced at |
|---|---|
Secret names must match ^[A-Z_][A-Z0-9_]*$ | loom check (schema validation) |
ref must be a non-empty string | loom check (schema validation) |
default.secrets is invalid | loom check (schema validation) |
A key cannot appear in both variables and secrets for the same job | loom check (schema validation) |
Malformed or unsupported ref URI | Runtime — SECRETS_REF_INVALID |
CI_DEBUG_TRACE=true with any file: false secret | Runtime — SECRETS_UNSAFE_DEBUG_TRACE |
Run loom check before every workflow run to catch schema-level issues early:
loom check
Error codes
| Code | Meaning | Typical fix |
|---|---|---|
SECRETS_PROVIDER_UNAVAILABLE | Provider auth or config is missing or invalid | Check OP_SERVICE_ACCOUNT_TOKEN or LOOM_KEEPASS_DB_* env vars |
SECRETS_REF_INVALID | Malformed or unsupported ref URI | Verify URI scheme and format against the provider's documentation |
SECRETS_REF_NOT_FOUND | Provider cannot find the referenced entry or field | Confirm the vault/database item exists with loom secrets <provider> item list |
SECRETS_REQUIRED_MISSING | A required: true secret could not be resolved | Fix the provider config, or set required: false if the secret is optional |
SECRETS_UNSAFE_DEBUG_TRACE | CI_DEBUG_TRACE=true combined with a file: false secret | Disable debug trace or switch the secret to file: true |
Provider-specific authoring
Each provider has its own URI format, authentication model, and runtime requirements:
- KeePass: Workflows secrets: KeePass — alias configuration, URI anatomy, runtime env vars
- 1Password: Workflows secrets: 1Password — service account token, Go SDK resolution, URI anatomy
- Provider reference docs: Secrets providers index — setup guides, CLI reference, and install instructions
Related docs
- Syntax (v1) — full workflow YAML reference
- Concepts: variables — how variables differ from secrets
- Getting started with secrets — end-to-end first-secret walkthrough
- Migrating from variables to secrets — move sensitive values out of
variablesblocks - Troubleshooting: diagnostics ladder — systematic failure triage