# Providers Reference

> Complete reference for SecretSpec storage providers and their URI configurations

SecretSpec supports multiple storage backends for secrets. Each provider has its own URI format and configuration options.

This page is a compact URI reference. For installation, authentication, copyable project configuration, storage behavior, and CI/CD guidance, follow the link for the individual provider. For the semantic authentication names accepted by those providers and their environment fallbacks, see the [provider credentials reference](/reference/provider-credentials/).

## Dotenv Provider

**URI**: `dotenv://[path]` - Stores secrets in `.env` files

```text
dotenv://                    # Uses default .env
dotenv:///config/.env        # Custom path
dotenv://config/.env         # Relative path
dotenv://~/.config/app/.env  # Home-relative path (0.18+)
```

**Features**: Read/write, profiles, human-readable, no encryption

## File Provider

**New in version 0.19**

**Changed in version 0.21**

File entries now preserve arbitrary bytes instead of requiring UTF-8.

**URI**: `file:ROOT` - Stores one plaintext file per secret beneath an explicitly configured local directory

`ROOT` is required. The bare `file` provider name is rejected.

```text
file:./.secrets              # Relative to secretspec.toml
file:///run/secrets          # Absolute directory
```

**Features**: Read/write/delete, project and profile isolation, exact bytes (0.21+), atomic writes, nested relative `ref.item` paths **Storage**: `ROOT/{project}/{profile}/{key}` by convention. A `ref.item` replaces the convention path with a relative path beneath `ROOT`. **Security**: No encryption. New files use mode `0600` on Unix; traversal and symbolic links inside the configured store are rejected.

## Environment Provider

**URI**: `env://` - Read-only access to system environment variables

```text
env://                       # Current process environment
```

**Features**: Read-only, no setup required, no persistence

## Null Provider

**New in version 0.19**

**URI**: `null://` - Always reports a missing value so the declaration’s committed `default`, configured generator, or `prompt = true` run input (0.19+) supplies the value

```text
null://                      # No configuration or storage
```

**Features**: No I/O, no authentication, no persistence, ordinary writes rejected; generated and prompted values are returned only for the current resolution or child invocation **Use case**: Non-sensitive configuration from the version-controlled manifest, or ephemeral generated/operator-supplied values that should be fresh for every resolution or run

## systemd Credential Provider

**New in version 0.17**

**Changed in version 0.21**

Credential files now preserve arbitrary bytes. Binary values require `as_path = true` at text consumption boundaries.

**URI**: `systemd-credential://` - Reads credentials passed to the current service by systemd

```text
systemd-credential://          # $CREDENTIALS_DIRECTORY
```

**Features**: Read-only, flat credential names, immutable service-lifetime values, provider-credential source support **Prerequisites**: A process started by systemd with `LoadCredential=`, `LoadCredentialEncrypted=`, `SetCredential=`, or `SetCredentialEncrypted=` **Storage**: One runtime file per credential under `$CREDENTIALS_DIRECTORY`; convention addresses use the SecretSpec key as the filename, and `ref.item` selects a different credential name

## Gopass Provider

**Changed in version 0.21**

Newly written entries preserve whitespace and multiline values. Writes use `gopass cat` and its lossless binary-entry format; use `gopass cat` to read these entries outside SecretSpec. Existing text entries retain password-only reads with surrounding whitespace removed.

Available starting with SecretSpec 0.15.

**URI**: `gopass://[host][path]` - Uses `gopass`, a multi-user and multi-store abstraction layer over `pass`, with GPG encryption

```text
gopass://                                    # Default folder prefix
gopass://secretspec/shared/{profile}/{key}   # Custom folder prefix with placeholders
```

**Features**: Read/write, GPG encryption, git-backed sync, profiles, local storage **Prerequisites**: `gopass` CLI, initialized password store **Storage**: Path `secretspec/{project}/{profile}/{key}` by default; the URI host and path override the folder prefix and support `{project}`, `{profile}`, and `{key}` placeholders

Text entries written by SecretSpec 0.20 or earlier, or with `gopass insert`, are read as a single line: only the first line is returned, with surrounding whitespace removed. Writing the secret again with `secretspec set` migrates it to the lossless format.

## Keyring Provider

**URI**: `keyring://` - Uses system keychain/keyring for secure storage

```text
keyring://                   # System default keychain
```

**Features**: Read/write, secure encryption, profiles, cross-platform **Storage**: Service `secretspec/{project}/{profile}/{key}`, with the current operating-system username as the account

## KeePass KDBX Provider

**New in version 0.17**

**URI**: `kdbx:PATH[?keyfile=PATH][&prefix=TEMPLATE]` - Stores secrets in a KeePass-compatible encrypted database

```text
kdbx:./secrets.kdbx
kdbx:/var/lib/myapp/secrets.kdbx
kdbx:./secrets.kdbx?keyfile=./secrets.key
kdbx:./shared.kdbx?prefix=teams/{project}/{profile}/{key}
```

**Features**: KDBX 3 read, KDBX 4 read/write, password and key-file authentication, standard and custom entry fields, profiles **Prerequisites**: Master password, key file, or both; build with `--features kdbx` (0.17+) **Authentication**: [`password` provider credential](/providers/kdbx/#provider-credentials) from a bootstrap provider (recommended), or the discouraged `SECRETSPEC_KDBX_PASSWORD` fallback; optional `?keyfile=PATH` **Storage**: Entry path `secretspec/{project}/{profile}/{key}`, field `Password` by default. A secret `ref` uses `item` for the complete group path and entry title, and optional `field` for a standard or custom field.

## LastPass Provider

**URI**: `lastpass://[item_template]` - Integrates with LastPass via `lpass` CLI

```text
lastpass://                                      # Default layout
lastpass://Work/SecretSpec/{project}/{profile}/{key} # Custom item template
```

**Features**: Read/write, cloud sync, profiles via folders, auto-sync **Prerequisites**: `lpass` CLI, authenticated with `lpass login` **Storage**: Item name `secretspec/{project}/{profile}/{key}` by default. A URI item template replaces the default and supports `{project}`, `{profile}`, and `{key}` placeholders.

## Dashlane Provider

**New in version 0.18**

**URI**: `dashlane://[item_type]` - Integrates with Dashlane via the `dcli` CLI

```text
dashlane://          # Search secrets, then logins, then notes
dashlane://note      # Secure notes only
dashlane://secret    # Dashlane Secrets only (Business plans)
dashlane://password  # Logins only
```

**Features**: Read-only, reads a locally synced vault, profiles via item titles **Prerequisites**: `dcli` CLI, device registered with `dcli sync`, or `DASHLANE_SERVICE_DEVICE_KEYS` for a non-interactive device **Storage**: Item titled `secretspec/{project}/{profile}/{key}`. The value is the item’s default field: `content` for a secret or note, `password` for a login. `dcli` cannot create or edit vault items, so `secretspec set` fails; author items in a Dashlane app and run `dcli sync`.

With `DASHLANE_SERVICE_DEVICE_KEYS` set, `dcli` runs against a private, owner-only state directory per credential, since it otherwise prefers an already-registered device and reads that identity’s vault instead. That state is separate from your own, so `dcli configure disable-auto-sync true` does not apply to it and those reads sync hourly.

## 1Password Provider

**URI**: `onepassword://[account@]vault` or `onepassword+token://vault`

```text
onepassword://MyVault              # Default account
onepassword://work@CompanyVault    # Specific account
onepassword+token://SecureVault    # Service account
```

The `onepassword+token://` scheme selects service account authentication; the token comes from the `service_account_token` provider credential or `OP_SERVICE_ACCOUNT_TOKEN`. Putting the token in the URI (`onepassword+token://token@vault`) is rejected from 0.19 on, since a URI ends up in committed manifests, shell history, and CI logs.

**Features**: Read/write, cloud sync, profiles via vaults, service accounts **Prerequisites**: `op` CLI, authenticated through desktop app integration, a service account token, or a legacy `op signin` shell session **Storage**: Secure Note named `secretspec/{project}/{profile}/{key}`, with tags `automated` and `{project}`

The URI names a vault only; item paths on the URI are rejected. To read and write an existing item’s field in place, name it with the `ref` field (`SECRET = { description = "…", ref = { item = "…", field = "…" } }`); see [Secret References](/reference/configuration/#secret-references).

## Keeper Secrets Manager Provider

**New in version 0.18**

**URI**: `keeper://FOLDER_UID[?config_file=PATH]` - Stores records in Keeper Secrets Manager through Keeper’s official Rust SDK

```text
keeper://SHARED_FOLDER_UID
keeper://SHARED_FOLDER_UID?config_file=.keeper/client-config.json
```

**Features**: Read/write/delete, end-to-end encryption, profile-aware record titles, standard and custom field references, batched retrieval **Prerequisites**: A Keeper Secrets Manager application with access to the selected folder; build with `--features keeper` (0.18+) **Authentication**: [`config` or `token` provider credentials](/providers/keeper/#provider-credentials), with `KSM_CONFIG` and `KSM_TOKEN` fallbacks; alternatively a bound `config_file`. **Storage**: Login record titled `secretspec/{project}/{profile}/{key}`, field `password`. A `ref` selects an existing record by UID or exact title and an optional standard/custom `field`.

## Doppler Provider

**New in version 0.21**

**Availability**: Added in SecretSpec 0.21 and included in default builds; use the `doppler` feature for a custom minimal build.

**URI**: `doppler://PROJECT[/CONFIG]` - Stores secrets in a Doppler project’s config over Doppler’s REST API

```bash
doppler://myapp               # the SecretSpec profile names the config
doppler://myapp/prd           # every profile reads the prd config
```

**Features**: Read/write/delete, verbatim secret names, profile-aware configs, batched retrieval of the declared names (one request per config), `${...}` reference resolution, name-only discovery through `init --from` **Prerequisites**: An existing Doppler project and config (SecretSpec does not create them) **Authentication**: `token` provider credential or `DOPPLER_TOKEN`. Both a service account token (`dp.sa.`) and a service token (`dp.st.`) work; a service token is pinned by Doppler to one project and config. **Storage**: Secret named `{key}`, verbatim, in the config named by the profile or by the pinned `CONFIG`. SecretSpec’s own project name is unused — the Doppler project provides the namespace. A `ref` selects a secret as `config/NAME`, or as a bare `NAME` when the URI pins a config.

## Pass Provider

**Changed in version 0.21**

Values keep their leading and trailing whitespace and multiline content. Entries are stored newline terminated, as the `pass` CLI writes them, and exactly one final newline is removed on read, so entries created with `pass insert` or `pass generate` resolve to their password.

**URI**: `pass://` - Uses Unix password manager with GPG encryption

```text
pass://                       # Default password store
```

**Features**: Read/write, GPG encryption, profiles, local storage **Prerequisites**: `pass` CLI, initialized with `pass init <gpg-key-id>` **Storage**: Path `secretspec/{project}/{profile}/{key}`

## Proton Pass Provider

**URI**: `protonpass://[vault[/title-template]]` - Stores secrets in Proton Pass via the official `pass-cli`

```text
protonpass://                                      # Default vault ("secretspec")
protonpass://Work                                  # Specific vault
protonpass://Work/{project}/{profile}/{key}        # Custom vault and title template
```

**Features**: Read/write, end-to-end encryption, cloud sync, vault organisation, PAT-based CI auth **Prerequisites**: `pass-cli`, authenticated with `pass-cli login` (or `pass-cli login --pat $PAT` for CI) **Storage**: Note item titled `{project}/{profile}/{key}` inside the configured vault

`pass-cli` ships backward incompatible changes in patch releases without advance notice, so a CLI upgrade can break secret resolution on its own. `pass-cli` 2.2.4 removed `pass-cli test`, which SecretSpec 0.18.0 and earlier use to check the session before every read and write; those releases need `pass-cli` 2.2.3 or earlier, while SecretSpec 0.19+ tries `pass-cli info` and falls back to `pass-cli test`, working with either. Pin a tested build and select it with `SECRETSPEC_PROTONPASS_CLI_PATH`. See [`pass-cli` compatibility](/providers/protonpass/#pass-cli-compatibility).

## Passbolt provider

**New in version 0.19**

**Availability**: Added in SecretSpec 0.19.

**URI**: `passbolt://[?server=URL][&folder=ID][&template=PATTERN]` - Reads and writes resources in a self-hosted Passbolt server through `go-passbolt-cli`

```text
passbolt://                                           # Default resource template
passbolt://?server=https://pass.example.com           # Select a server
passbolt://?folder=<folder-id>                         # Scope lookup and creation
passbolt://?template=teams/{project}/{profile}/{key}   # Replace the convention template
```

**Features**: Read/write, self-hosted, provider credentials, `init --from`, and `ref` by resource UUID or exact name (standard fields: `password`/`username`/`uri`/`description`; custom resource-type fields are not addressable)

**Prerequisites**: `go-passbolt-cli`, an OpenPGP private key, and its passphrase. Use the `private_key` and `passphrase` provider credentials, their `SECRETSPEC_PASSBOLT_*` environment fallbacks, or the CLI configuration. For MFA, the CLI supports TOTP only.

**Storage**: Resource `secretspec/{project}/{profile}/{key}`, field `password`. Missing resources named through `ref` are never created.

**Write limitation**: `go-passbolt-cli` accepts created/updated values only as flags, so a value being written is visible in the child process argv until it exits. See the [Passbolt provider security notes](/providers/passbolt/#security-considerations-and-limitations).

## Fly.io secrets provider

**New in version 0.20**

**Availability**: Added in SecretSpec 0.20.

**URI**: `fly://APP[?stage=true][&detach=true]` - Publishes application secrets through `flyctl secrets`

```text
fly://my-app                    # Update Machines and monitor the rollout
fly://my-app?stage=true         # Register changes without deploying them
fly://my-app?detach=true        # Start the rollout without monitoring it
```

**Features (0.20+)**: Write, delete, provider credentials, and name-only discovery through `init --from`; secret values are sent to `flyctl` over stdin instead of process arguments

**Prerequisites (0.20+)**: `flyctl`, an authenticated login or an `access_token` provider credential (`FLY_API_TOKEN` and `FLY_ACCESS_TOKEN` are fallbacks), and permission to manage the app named in the URI

**Storage (0.20+)**: Fly app secret `{key}`. The app URI, rather than the SecretSpec project or profile name, supplies isolation.

**Read limitation**: Fly.io exposes secret names and digests but never plaintext values. `get`, `check`, `run`, fallback reads, generation-on-miss, and prompting-on-miss cannot use this write-only provider. See the [Fly.io provider guide](/providers/fly/).

**Write limitation (0.20+)**: `flyctl` trims values read from stdin. SecretSpec rejects leading or trailing whitespace rather than silently publishing a different value.

## Cloudflare Secrets Store provider

**New in version 0.20**

**Availability**: Added in SecretSpec 0.20 and included in default builds; use the `cloudflare` feature for a custom minimal build.

**URI**: `cloudflare://STORE_ID[?account_id=ACCOUNT_ID][&scopes=LIST][&auth=MODE][&wrangler_profile=NAME]`

* Publishes account-level secrets through Cloudflare’s REST API

```text
cloudflare://STORE_ID?account_id=ACCOUNT_ID
cloudflare://STORE_ID?account_id=ACCOUNT_ID&auth=token
cloudflare://STORE_ID?account_id=ACCOUNT_ID&auth=wrangler&wrangler_profile=production
cloudflare://STORE_ID?account_id=ACCOUNT_ID&scopes=workers,containers
```

**Features (0.20+)**: Write, replace, delete, provider credentials, and name-only discovery through `init --from`; values are sent only in HTTPS request bodies

**Prerequisites (0.20+)**: A Cloudflare account and Secrets Store, account **Secrets Store Write** permission, the account and store IDs, and either an `api_token` provider credential, `CLOUDFLARE_API_TOKEN`, or credentials from `wrangler auth token --json`. `CLOUDFLARE_ACCOUNT_ID` is the fallback when the URI omits `account_id`.

**Storage (0.20+)**: Account secret `{key}` in the selected store. The store URI, rather than the SecretSpec project or profile name, supplies isolation. New and replaced entries receive the configured scopes, defaulting to `workers`.

**Read limitation (0.20+)**: Cloudflare’s management API exposes metadata but never plaintext secret values. `get`, `check`, `run`, fallback reads, generation-on-miss, and prompting-on-miss cannot use this write-only provider. Plaintext is available only inside a bound Cloudflare service. See the [Cloudflare provider guide](/providers/cloudflare/).

## Google Cloud Secret Manager Provider

**URI**: `gcsm://PROJECT_ID` - Stores secrets in Google Cloud Secret Manager

```text
gcsm://my-gcp-project         # GCP project ID
```

**Features**: Read/write, cloud sync, profiles, service account support **Prerequisites**: `gcloud` CLI, authenticated, Secret Manager API enabled, build with `--features gcsm` **Storage (0.20+)**: Secret name `secretspec2--{project}--{profile}--{key}` with validated, non-overlapping `--` boundaries. Releases through 0.19 used `secretspec-{project}-{profile}-{key}`. When the new id holds no value, reads fall back to the 0.19 id and warn; the fallback writes nothing, so no new permissions are needed. Writes always use the new id, so `secretspec set` is what moves a secret, and the 0.19 secret is left in place. Names accepted through 0.19 that the new layout cannot represent, such as a project containing `--`, keep reading their 0.19 secret and must be renamed before they can be written. Explicit `ref` addresses are unaffected.

## AWS Secrets Manager Provider

**Changed in version 0.21**

Reads and writes now support AWS `SecretBinary` as well as `SecretString`.

**URI**: `awssm://[profile@]REGION` - Stores secrets in AWS Secrets Manager

```text
awssm://us-east-1             # Specific AWS region
awssm://production@us-east-1  # Specific AWS profile and region
awssm://                      # SDK default region and credentials
```

**Features**: Read/write, `SecretString` and `SecretBinary` (0.21+), cloud sync, profiles, IAM/SSO authentication **Prerequisites**: AWS credentials configured, build with `--features awssm` **Storage**: Secret name `secretspec/{project}/{profile}/{key}`

## AWS Systems Manager Parameter Store Provider

**New in version 0.18**

**URI (0.18+)**: `awsps://[profile@]REGION[?prefix=PATH&template=TEMPLATE&kms_key_id=KEY&tier=TIER]`

* Stores secrets as encrypted AWS Systems Manager Parameter Store values; `prefix` and `template` are mutually exclusive.

```text
awsps://us-east-1                                  # Specific AWS region
awsps://production@us-east-1                       # AWS profile and region
awsps://us-east-1?prefix=/team                     # Additional hierarchy
awsps://us-east-1?template=/{profile}/{project}/{key} # Replace the hierarchy
awsps://us-east-1?kms_key_id=alias/key&tier=advanced
awsps://                                           # SDK defaults
```

**Features (0.18+)**: Read/write, `SecureString` encryption, cloud sync, profiles, IAM/SSO authentication, batched reads, version- or label-pinned read-only refs, writable unversioned parameter-name refs; ARN refs are read-only **Prerequisites (0.18+)**: AWS credentials configured, build with `--features awsps` **Storage (0.18+)**: Parameter `[/prefix]/secretspec/{project}/{profile}/{key}`. `template` replaces the complete layout and must end in `/{key}`; `kms_key_id` selects a customer-managed key, while `tier` accepts `standard`, `advanced`, or `intelligent-tiering` **Discovery (0.18+)**: Bounded declaration discovery through `init --from`

## Scaleway Secret Manager Provider

**New in version 0.17**

**URI**: `scaleway://[REGION][?project_id=UUID&path=/folder]` - Stores secrets in Scaleway Secret Manager

```text
scaleway://fr-par                                    # Region, project from SCW_DEFAULT_PROJECT_ID
scaleway://nl-ams?project_id=PROJECT_UUID            # Region and project
scaleway://fr-par?project_id=PROJECT_UUID&path=/team # Nest under a folder
scaleway://                                          # Region from SCW_DEFAULT_REGION, else fr-par
```

**Features**: Read/write, cloud sync, profiles via folders, version-pinned refs, JSON-key refs **Prerequisites**: Scaleway API secret key (`secret_key` credential or `SCW_SECRET_KEY`), build with `--features scaleway` **Storage**: Folder `[{base}/]secretspec/{project}/{profile}`, secret name `{key}`

## Tailscale Setec Provider

**New in version 0.21**

**URI**: `setec://HOST[:PORT][?prefix=PATH][&tls=false]` - Uses a Tailscale Setec server

```text
setec://secrets.example.ts.net
setec://secrets.example.ts.net?prefix=platform
setec://127.0.0.1:8080?tls=false
```

**Features**: Read/write/delete, version-pinned reads, project/profile isolation, and bounded discovery **Authentication**: The caller’s Tailscale identity and Setec grants **Storage**: `[prefix/]secretspec/{project}/{profile}/{key}`; a native `ref.item` names an exact Setec secret and optional `ref.version` selects a specific version **Prerequisites**: Reachability to the Setec server over the tailnet; build with `--features setec` (0.21+)

## Vault Provider

**URI**: `vault://[namespace@]host[:port][/mount][?options]` - Stores secrets in HashiCorp Vault’s KV engine

```text
vault://vault.example.com:8200/secret       # KV v2 at "secret" mount
vault://vault.example.com:8200              # Default "secret" mount
vault://ns1@vault.example.com:8200/secret   # With namespace
vault://vault.example.com:8200/secret?auth=approle
# SecretSpec 0.17+
vault://vault.example.com:8200/secret?auth=jwt&role=ci
# SecretSpec 0.18+
vault://vault.example.com:8200/secret?auth=approle&auth_mount=platform-approle
# SecretSpec 0.18+, with default_role configured on the JWT auth mount
vault://vault.example.com:8200/secret?auth=jwt
vault://127.0.0.1:8200/secret?kv=1         # KV v1 engine
vault://127.0.0.1:8200/secret?tls=false    # Disable TLS (dev mode)
```

**Features**: Read/write, KV v1 and v2, namespaces; token and AppRole authentication, including AppRoles without SecretID binding (0.18+); JWT/OIDC authentication (0.17+); custom AppRole/JWT mounts and server-default JWT roles (0.18+) **Prerequisites**: Vault server, authentication credentials, build with `--features vault` **Storage**: KV path `secretspec/{project}/{profile}/{key}` with a `value` field

## OpenBao Provider

**New in version 0.17**

**URI**: `openbao://[namespace@]host[:port][/mount][?options]` - Stores secrets in OpenBao’s KV engine

```text
openbao://bao.example.com:8200/secret
openbao://team-a@bao.example.com:8200/secret
openbao://bao.example.com:8200/secret?auth=approle
openbao://bao.example.com:8200/secret?auth=jwt&role=ci
# SecretSpec 0.18+
openbao://bao.example.com:8200/secret?auth=jwt&auth_mount=ci-jwt&role=ci
# SecretSpec 0.18+, with default_role configured on the JWT auth mount
openbao://bao.example.com:8200/secret?auth=jwt
openbao://127.0.0.1:8200/secret?kv=1&tls=false
```

**Features**: Read/write, KV v1 and v2, namespaces; token, AppRole, and JWT/OIDC authentication; AppRoles without SecretID binding, custom AppRole/JWT mounts, and server-default JWT roles (0.18+); documented OpenBao CLI variables plus SecretSpec-defined `BAO_*` AppRole/JWT inputs, all with `VAULT_*` compatibility fallbacks **Prerequisites**: OpenBao server, authentication credentials, build with `--features openbao` (0.17+) **Storage**: KV path `secretspec/{project}/{profile}/{key}` with a `value` field

## Bitwarden Password Manager Provider

**New in version 0.18**

**URI**: `bw://[COLLECTION]` - Stores secrets in a Bitwarden Password Manager vault via the `bw` CLI

```text
bw://                                   # Personal vault
bw://dev-secrets                        # Collection, by name or ID
bw://myorg@dev-secrets                  # Organization and collection
bw://?server=https://vault.company.com  # Expected self-hosted server (guard)
bw://?type=login&field=username         # Default item type and field
bw://?folder=team/{project}/{profile}   # Convention title prefix (0.20+)
```

Organizations and collections may be named or given as IDs; SecretSpec resolves a name to the ID the CLI requires, matching case-insensitively. The organization scopes and validates the collection rather than filtering alongside it: it selects which `dev-secrets` is meant when more than one exists, and must match the collection’s actual organization. Naming it is optional when the collection name is unambiguous. Addresses that resolve to nothing fail with the organizations or collections that do exist.

**Changed in version 0.21**

`ref.item` also accepts an exact Bitwarden item UUID.

An exact item UUID selects that item directly. Otherwise, item names match the same way — **in full and case-insensitively** (0.18+), so `API_KEY` never resolves `API_KEY_OLD`. Names are not unique in Bitwarden, and a name matching several items is refused with their ids rather than resolved to an arbitrary one; address a single item by using its id as the `item`. `?type=` narrows name matches on both reads and writes, keeping a Card and a same-named Login separately addressable. An exact item UUID takes precedence because it already identifies one item. An unsupported `?type=`, or an unknown query parameter, is rejected when the address is parsed rather than ignored.

SecretSpec 0.20+ convention items use the title `secretspec/{project}/{profile}/{key}`. `?folder=` replaces the prefix before the key; it is an item-title namespace, not a Bitwarden folder. Explicit `ref.item` values remain complete, unprefixed item titles or, in 0.21+, exact item UUIDs. Releases through 0.19 wrote bare convention titles, which must be renamed to the 0.20 layout or kept with an explicit `ref = { item = "OLD_TITLE" }`; there is no automatic bare-name fallback because a bare item carries no project/profile ownership.

`?server=` does not configure the CLI. The `bw` CLI takes its server only from `bw config server`, which must be run while logged out, so self-hosted users configure the CLI themselves and SecretSpec verifies the setting matches before each operation. See the [provider guide](/providers/bw/#self-hosted-servers).

**Features**: Read/write, all vault item types (logins, cards, identities, SSH keys, secure notes), organization/collection addressing by name or ID, field selection, `ref = { item, field }` mapping in `secretspec.toml`, declaration discovery through `init --from` (0.18+) **Prerequisites**: Bitwarden CLI (`bw`), signed in and unlocked (`BW_SESSION` env var), self-hosted servers set with `bw config server` before login, build with `--features bw` **Storage**: One vault item per secret; convention title `secretspec/{project}/{profile}/{key}` (0.20+, customizable with `?folder=`), with per-type default fields unless `?field=` or a `ref` mapping selects one

## Bitwarden Secrets Manager Provider

**URI**: `bws://[SERVER_BASE@]PROJECT_UUID` - Stores secrets in Bitwarden Secrets Manager

```text
bws://a9230ec4-5507-4870-b8b5-b3f500587e4c                    # US cloud (default)
bws://vault.bitwarden.eu@a9230ec4-5507-4870-b8b5-b3f500587e4c # EU cloud
bws://bw.example.com@a9230ec4-5507-4870-b8b5-b3f500587e4c     # Self hosted
```

`SERVER_BASE` is the bare hostname of the Bitwarden instance. SecretSpec 0.17+ passes `https://SERVER_BASE` to `bws --server-url`; SecretSpec 0.16 and earlier derive the `https://SERVER_BASE/identity` and `https://SERVER_BASE/api` endpoints through the SDK. Omit it to use the `bitwarden.com` US cloud.

**Features**: Read/write, cloud sync, project-scoped, end-to-end encryption **Prerequisites**: BWS subscription, machine account access token, build with `--features bws` **Storage**: Flat key names in the specified BWS project

SecretSpec 0.17 and later require the official `bws` CLI 0.3.0 or later on `PATH` and invoke it for all reads and writes; set `SECRETSPEC_BWS_CLI_PATH` to use another executable path. The access token is supplied through the child process environment. Secret values passed to the CLI for creation or editing may briefly be visible to same-user process-inspection tools.

## Azure Key Vault Provider

**URI**: `akv://VAULT_NAME[?auth=env|cli|managed_identity|workload_identity][&suffix=DNS_SUFFIX]` - Stores secrets in Azure Key Vault

```text
akv://myvault                            # Service principal env vars, falling back to `az login`
akv://myvault?auth=managed_identity      # VM / App Service / AKS system-assigned managed identity
akv://myvault?auth=workload_identity     # AKS workload identity federation
akv://myvault.vault.azure.cn             # Sovereign cloud (full DNS name)
akv://myvault?suffix=vault.azure.cn      # Sovereign cloud (explicit suffix, bare vault name)
```

**Features**: Read/write, cloud sync, profiles, service principal/managed identity/workload identity auth, version-pinned refs (0.20+) **Prerequisites**: An Azure Key Vault instance, authenticated via one of the methods above, build with `--features akv` **Storage**: Secret name `secretspec--{base32(project)}--{base32(profile)}--{base32(key)}` (lowercase, unpadded Base32 preserves case and punctuation distinctions within Azure’s case-insensitive secret-name namespace)

## Azure App Configuration Provider

**New in version 0.20**

**URI**: `aac://STORE[?auth=METHOD][&label=LABEL][&prefix=PREFIX][&tag=NAME=VALUE]...`

* Reads and manages Azure App Configuration key-values and resolves canonical Azure Key Vault references

```bash
aac://payments-production
aac://shared?label=production&prefix=payments:
aac://shared?tag=app=payments&tag=stage=production
aac://shared?auth=connection_string&key_vault_auth=managed_identity
```

**Features (0.20+)**: Read/write/delete, project and profile namespacing, declaration discovery, exact label and tag selection, sovereign-cloud endpoint configuration, Entra or connection-string authentication, and Key Vault reference resolution **Prerequisites (0.20+)**: An Azure App Configuration store and matching data-plane permissions. Official and default builds include AAC; custom minimal builds use `--features aac`. Key Vault references also require an Entra identity with secret-read access. **Authentication (0.20+)**: `env`, `cli`, `managed_identity`, `workload_identity`, or `connection_string`. Prefer Entra authentication so workloads use Azure RBAC without distributing App Configuration access keys; reserve connection strings for environments where Entra is unavailable. See the [provider guide](/providers/aac/#authentication) for App Configuration and Key Vault identity separation. **Storage (0.20+)**: `{prefix}secretspec:{project}:{profile}:{key}` under one exact label; omission selects the null label

## Infisical Provider

Available since SecretSpec 0.16.

**URI**: `infisical://[HOST]/PROJECT_ID[?env=SLUG][&path=/PREFIX][&tls=false]` - Stores secrets in Infisical

```text
infisical://app.infisical.com/7e2f1a4c-...            # Infisical Cloud (US)
infisical://eu.infisical.com/7e2f1a4c-...             # Infisical Cloud (EU)
infisical://vault.example.com/7e2f1a4c-...?env=prod   # Read every profile from one environment
infisical://localhost:8080/7e2f1a4c-...?tls=false     # Self-hosted over plain HTTP
```

The project is Infisical’s project **UUID** (Project Settings → Project ID); its API does not accept the project slug. Without a host, the provider reads `INFISICAL_DOMAIN`, then Infisical’s legacy `INFISICAL_API_URL`, then defaults to Infisical Cloud.

**Features**: Read/write, cloud sync, profiles, machine-identity (Universal Auth) or token auth, secret references, version-pinned refs **Prerequisites**: An Infisical project, a machine identity with access to it, build with `--features infisical` **Authentication**: `INFISICAL_CLIENT_ID` + `INFISICAL_CLIENT_SECRET` (Universal Auth), or a ready-made `INFISICAL_TOKEN`. Service tokens are not supported; Infisical deprecated them in favour of machine identities. **Storage**: Secret `{key}` in folder `/secretspec/{project}/{profile}`, in the environment named by the profile (or by `?env=`). Keys are stored verbatim.

By default the SecretSpec profile names the Infisical environment, so a `production` profile reads the `production` environment. This covers refs as well as convention naming (0.20+). Projects whose environments do not correspond to profiles pin one with `?env=`; the profile still names the folder, so profiles never share a secret.

Infisical uses the same 404 for a missing secret, folder, environment, or project. In SecretSpec 0.20+, an all-missing read checks the environment root once and reports a missing environment or project, including whether the profile or `?env=` selected the environment. Ordinary missing secrets and folders remain unset so provider fallback continues.

Values are read with Infisical’s secret references expanded, matching its own CLI, so a value of `postgres://${DB_USER}@host` arrives resolved.

## EJSON Provider

**New in version 0.20**

**URI**: `ejson:PATH` - Reads string values from one EJSON encrypted file

```text
ejson:secrets.ejson
ejson:config/secrets.production.ejson
ejson:///var/run/application/secrets.ejson
```

**Features (0.20+)**: Read-only, RFC 6901 JSON Pointer references, project/profile convention pointers, exact provider-credential key sources, and one decryption per batch **Prerequisites (0.20+)**: EJSON 1.1.0 or later, an encrypted EJSON file, and its matching private key; build with `--features ejson` **Authentication (0.20+)**: The `private_key` provider credential. It has no environment or URI fallback; source it from an exact provider reference such as a Google Cloud Secret Manager secret and version. **Storage (0.20+)**: Convention reads use `/{project}/{profile}/{key}` in the decrypted JSON document. A native `ref.item` is any RFC 6901 JSON Pointer selecting a string.

The provider decrypts the complete EJSON document in memory through the current official CLI, then returns only requested values. Encrypted input and decrypted output are each limited to 16 MiB. It writes no decrypted value to a file itself. On Unix, SecretSpec opens the configured path with no-follow and nonblocking semantics, copies ciphertext into an anonymous inherited descriptor, and stops the CLI process group after a 30-second timeout. Other platforms use a private named ciphertext snapshot. Parent-directory resolution still requires a trusted path. The provider rejects writes, non-string selected values, URI credentials, ports, query options, fragments, and native coordinates other than `item`. EJSON properties beginning with `_` are plaintext metadata and must not contain secrets.

See the [EJSON provider guide](/providers/ejson/) for exact Google Cloud Secret Manager credential configuration and security limitations.

## age Provider

**New in version 0.17**

**URI**: `age://PATH[?identity=FILE][&recipients-file=FILE][&armor=false]` - Stores secrets in a single age-encrypted file committed alongside code

```text
age://secrets.age                                        # Encrypt to your own identity
age://secrets.age?identity=/home/alice/.config/age/plugin-identity.txt
age://secrets.age?recipients-file=secrets.age.recipients # Share with a roster
```

**Features**: Read/write, delete (0.20+), committed-file storage, X25519 and SSH keys, native tagged recipients, and non-interactive `age-plugin-*` recipients and identities **Prerequisites**: An age identity; hybrid ML-KEM-768 + X25519 keys from `age-keygen -pq` are recommended for new setups and currently require the non-interactive `age-plugin-pq` compatibility plugin. Build with `--features age`. **Authentication**: The `identity` credential, `AGE_IDENTITY`, or `?identity=`; recipients from `?recipients-file=` or derived from the identity **Storage**: One `KEY=value` entry per secret inside the encrypted blob at PATH

## SOPS Provider

**New in version 0.17**

**URI**: `sops://PATH[?format=yaml|json|dotenv|ini]` - Stores secrets in a SOPS-encrypted file or a templated set of files

```text
sops://secrets.enc.yaml
sops://secrets/{project}/{profile}.enc.json
sops://secrets/{project}/.env.{profile}.enc?format=dotenv
```

**Features**: Read/write, YAML, JSON, dotenv, and INI files, SOPS key-service support, and profile-aware templated paths **Prerequisites**: The `sops` CLI and the required SOPS key configuration; build with `--features sops` (0.17+) **Authentication**: SOPS environment variables or the [supported provider credentials](/providers/sops/#provider-credentials) **Storage**: Single-file YAML and JSON convention writes use `[project][profile][key]`; single-file INI uses `[profile][key]`, and dotenv is flat. Templated paths use a root key (or `[DEFAULT][key]` for INI) in one file per project/profile. A single-file provider supports `ref = { item = "..." }` as a root key (or a key in `[DEFAULT]` for INI); extra coordinates and refs through templated paths are rejected.

## Kubernetes Provider

**New in version 0.20**

**URI**: `k8s+KIND://NAME[@NAMESPACE]` - Stores secrets in a Kubernetes ConfigMap or Secret

```text
k8s+configmap://db-config@db-postgres
k8s+configmap://db-config
k8s+secret://db-credentials@db-postgres
```

**Features**: Read/write Kubernetes ConfigMaps and Secrets **Prerequisites**: A Kubernetes configuration in `$KUBECONFIG` or `$HOME/.kube/config`; build with `--features kubernetes` (0.20+) **Authentication**: Configured in Kubernetes configuration **Storage**: `secretspec--{project}--{profile}--{key}` key under `.data` in the Kubernetes object

## Provider Selection

### Command Line

```bash
# Simple provider names
$ secretspec get API_KEY --provider keyring


$ secretspec get API_KEY --provider dotenv


$ secretspec get API_KEY --provider env


# URIs with configuration
$ secretspec get API_KEY --provider dotenv:/path/to/.env


$ secretspec get API_KEY --provider onepassword://vault


$ secretspec get API_KEY --provider "onepassword://account@vault"
```

### Environment Variables

```bash
$ export SECRETSPEC_PROVIDER=keyring


$ export SECRETSPEC_PROVIDER="dotenv:///config/.env"
```

## Security Considerations

| Provider                         | Encryption                         | Storage Location                                           | Network Access                    |
| -------------------------------- | ---------------------------------- | ---------------------------------------------------------- | --------------------------------- |
| Dotenv                           | ❌ Plain text                       | Local filesystem                                           | ❌ No                              |
| File (0.19+)                     | ❌ Plain text                       | Local filesystem                                           | ❌ No                              |
| Environment                      | ❌ Plain text                       | Process memory                                             | ❌ No                              |
| Null (0.19+)                     | N/A — no stored value              | None                                                       | ❌ No                              |
| systemd Credential (0.17+)       | Depends on unit source             | systemd-managed runtime memory                             | ❌ No                              |
| Keyring                          | ✅ System encryption                | System keychain                                            | ❌ No                              |
| KeePass KDBX (0.17+)             | ✅ KDBX encryption                  | Local filesystem                                           | ❌ No                              |
| Pass                             | ✅ GPG encryption                   | Local filesystem                                           | ❌ No                              |
| Gopass                           | ✅ GPG encryption                   | Local filesystem                                           | ❌ No                              |
| Proton Pass                      | ✅ End-to-end                       | Cloud (Proton)                                             | ✅ Yes                             |
| Passbolt (0.19+)                 | ✅ End-to-end                       | Self-hosted (Passbolt server)                              | ✅ Yes                             |
| Fly.io secrets (0.20+)           | ✅ Fly.io-managed                   | Cloud (Fly.io app vault)                                   | ✅ Yes                             |
| Cloudflare Secrets Store (0.20+) | ✅ Cloudflare-managed               | Cloud (account-level store)                                | ✅ Yes                             |
| LastPass                         | ✅ End-to-end                       | Cloud (LastPass)                                           | ✅ Yes                             |
| Dashlane (0.18+)                 | ✅ End-to-end                       | Cloud (Dashlane), synced locally                           | Yes — `dcli` auto-syncs hourly    |
| 1Password                        | ✅ End-to-end                       | Cloud (1Password)                                          | ✅ Yes                             |
| Keeper (0.18+)                   | ✅ End-to-end                       | Cloud (Keeper)                                             | ✅ Yes                             |
| Doppler (0.21+)                  | ✅ Doppler-managed                  | Cloud (Doppler)                                            | ✅ Yes                             |
| GCSM                             | ✅ Google-managed                   | Cloud (GCP)                                                | ✅ Yes                             |
| AWSSM                            | ✅ AWS KMS                          | Cloud (AWS)                                                | ✅ Yes                             |
| AWS Parameter Store (0.18+)      | ✅ AWS KMS (`SecureString`)         | Cloud (AWS)                                                | ✅ Yes                             |
| Scaleway (0.17+)                 | ✅ Scaleway-managed                 | Cloud (Scaleway)                                           | ✅ Yes                             |
| Tailscale Setec (0.21+)          | ✅ Server-managed encryption        | Self-hosted Setec server                                   | ✅ Yes, over the tailnet           |
| Vault                            | ✅ Vault encryption                 | Vault server                                               | ✅ Yes                             |
| OpenBao (0.17+)                  | ✅ OpenBao encryption               | OpenBao server                                             | ✅ Yes                             |
| BW (0.18+)                       | ✅ End-to-end                       | Cloud (Bitwarden) or self-hosted                           | ✅ Yes                             |
| BWS                              | ✅ End-to-end                       | Cloud (Bitwarden)                                          | ✅ Yes                             |
| AKV                              | ✅ Azure-managed                    | Cloud (Azure)                                              | ✅ Yes                             |
| Azure App Configuration (0.20+)  | ✅ Azure-managed                    | Cloud (Azure)                                              | ✅ Yes                             |
| Infisical                        | ✅ Infisical-managed                | Cloud (Infisical) or self-hosted                           | ✅ Yes                             |
| EJSON (0.20+)                    | ✅ EJSON encryption                 | Local encrypted file; private key from configured provider | Depends on private-key provider   |
| age (0.17+)                      | ✅ age encryption                   | Local filesystem                                           | ❌ No                              |
| SOPS (0.17+)                     | ✅ Configured SOPS encryption       | Local filesystem                                           | Depends on configured key service |
| Kubernetes (0.20+)               | ❌ ConfigMap ✅ Secret if configured | Kubernetes server                                          | ✅ Yes                             |