Skip to content

0.21.0 - 2026-09-22

Latest

Choose a tag to compare

@github-actions github-actions released this 23 Sep 05:09
eeb1845

Release Notes

SecretSpec 0.21 lets other programs request only the secrets they need, lets
providers run outside SecretSpec, and preserves binary values from storage to
the consuming application. It also adds Doppler and Tailscale Setec providers,
project-wide provider defaults, and a Claude Code credential integration.

Changed

  • Cached values use a new format to preserve binary secrets. Existing cache
    entries remain readable by 0.21. SecretSpec 0.20 and earlier cannot read new
    entries; they fall back to the original provider and leave those entries
    untouched. Avoid sharing a cache store between 0.20 and 0.21 clients.

  • Command-generated values now include all stdout bytes, including spaces
    and a final newline. For example, openssl rand -hex 32 produces a value
    ending in \n; trim it in the command if that is unwanted. Existing stored
    values do not change. Empty or whitespace-only output is still rejected.

  • Piped secretspec set input remains trimmed text. Use --from-file -
    when whitespace or non-UTF-8 bytes must be preserved from stdin.

  • secretspec get no longer adds a newline when writing to a pipe or file.
    This makes redirects preserve the exact value. Terminal output still ends in
    a newline; shell command substitution behaves as before.

  • Rust secrets are byte values. Secrets::set now takes SecretBytes.
    Replace set(name, Some(value)) with set_text(name, &value) for text and
    set(name, None) with prompt_and_set(name). Custom providers must update
    their get, set, and get_many implementations to use SecretBytes;
    Provider::name now returns &str, and generator::generate returns bytes.

  • Building the new C resolver client requires system yyjson. Meson finds it
    through pkg-config and CMake through find_package(yyjson CONFIG). Static
    consumers must link -lyyjson; secretspec-resolver.pc records the dependency.

Added

  • Resolve secrets from another process. secretspec serve exposes a
    private, versioned stdio protocol so an application can request one declared
    secret without loading the whole manifest into its own process. It can return
    a value or a temporary file that is cleaned up when the session ends. Clients
    can also answer prompts, store or delete declared secrets on the same provider
    route, and receive expiry and revision information for their own caches.
    secretspec serve --read-only refuses operations that would write, including
    generation and prompting when they would store a value. Applications can use
    the Rust secretspec-ipc crate (async or blocking), the C
    libsecretspec-resolver library, or the protocol directly. Rust clients can
    also connect over SSH or an existing authenticated stream.

  • Install providers outside the SecretSpec release cycle. Trusted external
    executables can register as providers and serve a versioned provider protocol.
    They can describe their capabilities, request credentials for their own URI,
    and return an interaction reference that appears in the audit log for an
    approval flow. secretspec config provider login and secretspec set can
    collect missing credentials. SecretSpec passes each endpoint only the
    base environment plus the variables it declared, keeping other providers'
    tokens separate.

  • Keep binary secrets intact. Providers, fallback chains, imports, and the
    cache now preserve arbitrary bytes. Use secretspec set NAME --from-file FILE
    (or --from-file - for stdin) to store exact bytes, and as_path = true to
    pass them to an application through a temporary file. The file, systemd
    credential, environment, keyring, Google Secret Manager, Kubernetes, and
    Scaleway providers support binary values; AWS Secrets Manager also supports
    SecretBinary. Rust callers can use resolve_bytes() and
    resolve_named_bytes(). Text-only outputs report a UTF-8 error naming the
    secret. On Unix, run passes non-UTF-8 values to child processes; it rejects
    NUL bytes before launching them.

  • Doppler provider (doppler://PROJECT[/CONFIG]): read, write, delete, and
    discover secrets in an existing Doppler project. It keeps names unchanged so
    secrets remain usable in the Doppler dashboard and doppler run. The active
    SecretSpec profile selects the Doppler config unless the URI pins one.
    Authenticate with DOPPLER_TOKEN or a token provider credential. Doppler
    restrictions and values it cannot store unchanged are reported as errors.

  • Tailscale Setec provider (setec://): read, write, delete, and discover
    secrets through a tailnet-authenticated Setec server. It supports binary
    values and reads pinned to a Setec version.

  • Set a project-wide provider chain with [defaults].providers. Secrets
    without their own or a profile-level chain use this default, so a checked-in
    manifest can refer to an alias that each developer maps to their preferred
    store. User-global alias ref templates can expand {project}, {profile},
    and {key}. Native SDK inline declarations support this through schema v2;
    v1 declarations still work.

  • Use SecretSpec credentials with Claude Code. secretspec claude configure
    installs an apiKeyHelper that retrieves Anthropic API or gateway credentials
    from any provider. login and logout manage them by settings scope and API
    resource; unconfigure removes the managed helper without replacing unrelated
    settings. Repository, user, worktree, and CLAUDE_CONFIG_DIR settings are
    supported.

  • Get editor help for configuration. Export JSON Schemas for
    secretspec.toml and user config.toml with secretspec schema --config project or secretspec schema --config global for autocomplete, field
    descriptions, and validation.

  • Generate OpenPGP and OpenSSH private keys. Use
    type = "openpgp_private_key" with generate.user_id, or
    type = "ssh_private_key". Both generate modern keys by default and offer
    RSA for compatibility; OpenPGP keys can be limited to signing or encryption.

  • Target a specific Bitwarden item by UUID when several items share a name.
    Reads and writes accept the UUID, and imports reject duplicate item fields
    before making changes.

  • Declare JVM SDK secrets inline with withInlineSpec instead of requiring
    a manifest file.

Fixed

  • Stalled HTTP providers fail in bounded time. Vault, OpenBao, Infisical,
    Cloudflare, Scaleway, Azure App Configuration, Doppler, and Setec use a
    10-second connection timeout and a 60-second request timeout. Vault and
    OpenBao now retry timed-out requests as configured.

  • macOS keyring access no longer asks for the login keychain password on
    every run after an upgrade.
    A new build may ask once per existing item;
    choose "Always Allow" to keep later runs of that build quiet. Reads preserve
    the item and its access settings, even if access is denied.

  • KeePassXC KDBX 4.0 files can be written. SecretSpec upgrades them to
    KDBX 4.1 on write while preserving their encryption and key-derivation
    settings.

  • Bitwarden reads are faster and more consistent. A batch uses one vault
    listing, and a single read falls back to the full listing if Bitwarden's
    search returns only similarly named items.

  • pass, gopass, and LastPass handle whitespace and multiline values more
    reliably.
    The pass provider removes one final newline added by the pass
    CLI on read. Existing gopass text entries still return their trimmed first
    line until rewritten; new values requiring exact bytes use its binary-entry
    format. Ordinary single-line gopass values remain readable by older tools.
    LastPass rejects NUL bytes before writing rather than silently truncating
    them.

  • Cache planning avoids unnecessary provider reads and refuses a cache
    that would point to the same physical secret as its source under the active
    profile, preventing an overwrite or deletion of the source value.

Install secretspec 0.21.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/cachix/secretspec/releases/download/v0.21.0/secretspec-installer.sh | sh

Download secretspec 0.21.0

File Platform Checksum
secretspec-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
secretspec-x86_64-apple-darwin.tar.xz Intel macOS checksum
secretspec-x86_64-pc-windows-msvc.zip x64 Windows checksum
secretspec-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
secretspec-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
secretspec-aarch64-unknown-linux-musl.tar.xz ARM64 MUSL Linux checksum
secretspec-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum