Release Notes
Changed
- A provider URI may no longer carry a credential. A URI with a password
(scheme://user:secret@host) is rejected, andonepassword+token://no
longer accepts the service account token in its userinfo
(onepassword+token://token@vault). A URI is committed tosecretspec.toml,
echoed into shell history, and printed by CI, so a credential written there is
already disclosed and redacting it at the terminal cannot retract it. Keep the
scheme and supply the credential through a provider credential
(secretspec config provider login <alias>, orcredentials = { ... }on the
alias) or the provider's environment variable; the errors name both. An
unparseable provider specification is now also redacted before it is reported. secretspec getresolves through the same path as the SDK'sresolve_named,
so a single-secret read makes exactly the decisions batch resolution makes. It
continues to read the whole profile regardless of an active scope, and audits
the coordinates it actually reached.- 1Password field references now resolve in one batched CLI call, reducing
repeated unlocks and process startup when loading multiple secrets. If a
missing reference requires individual reads, those reads remain bounded and
concurrent. - The Rust SDK's
ProviderAliasnow providesleaf,credentials, and
credentials_muthelpers so callers can construct and inspect leaf or
inline-cached aliases without depending on their storage representation.
Added
- The Rust SDK can resolve a single secret with
Secrets::resolve_named, which
reads only that secret and the inputs it composes from. An unrelated missing
required secret no longer fails the call, and the result distinguishes an
undeclared name (including one the active scope hides) from a declared secret
with no value, reporting whether that value was required. Secrets::with_default_reasonsets a session reason only when none is already
in effect, so an embedding application can describe itself without discarding
the reason its own caller supplied throughwith_reasonor
SECRETSPEC_REASON.- Secrets can set
prompt = trueto request a hidden value from the controlling
terminal whensecretspec runfinds no stored value. Writable providers save
the answer for later runs; thenullprovider keeps it invocation-only. - Profiles can opt out of inheriting
[profiles.default]by setting
inherit = falsein their profile defaults (0.19+), allowing standalone
secret sets alongside profiles that still share the default declarations. - Passbolt provider (
passbolt://): store and read secrets in a
self-hosted Passbolt server through the community-maintained
go-passbolt-cli, with convention-based names, references to existing
resources, and credentials supplied by the CLI configuration or SecretSpec
provider environment variables. - Provider aliases can define native
reftemplates and secrets can override
coordinates per leaf alias withrefs, so fallback providers and import
sources/destinations resolve independently.import --delete-sourcenow
preflights the whole migration, verifies all writes before cleanup, and can
safely move between distinct entries in the same physical store. - A
nullprovider lets non-sensitive, version-controlled environment values
use their manifest defaults and lets generated secrets stay ephemeral, with a
fresh value returned for each resolution and nothing written to provider
storage. secretspec setand interactivesecretspec checknow preview the resolved
write destination before reading the value, including the exact file and
selector for SOPS.- A
fileprovider stores each secret as one plaintext UTF-8 file beneath an
explicitly configured relative or absolute directory, with project/profile
isolation and support for existing file-mounted secrets throughref.item. - Secrets can select values from stored JSON documents with RFC 6901 pointers
usingextract. Extraction composes with provider-native references and
storage decoding; selected values are read-only so sibling document data is
never overwritten or deleted. - Secrets can store values as standard Base64, URL-safe Base64, or hexadecimal
usingencoding; writes encode logical text and reads decode stored values,
whileas_path = truematerializes arbitrary decoded bytes. secretspec-ffiinstalls (viacargo cinstall) together with its C header
and asecretspec_ffi.pc, so consumers can link it — statically or
dynamically — without hand-written linker flags.- The Haskell SDK's new
use-pkg-configcabal flag
(cabal build -f use-pkg-config) resolves an installed static or shared
library through pkg-config. - The Ruby SDK's native extension accepts a new
--enable-pkg-configbuild
flag (gem install secretspec -- --enable-pkg-config) that resolves an
installed static or shared library through pkg-config. - The Go SDK has a new
pkgconfigbuild tag (go build -tags pkgconfig) that
links an installed static or shared library, so it also works for ago get
dependency. - The Haskell SDK declares the archive's macOS system frameworks
(SystemConfiguration,Security,CoreFoundation) in its cabal file, so
GHC passes them to every link on macOS. - A single provider can now attach its cache directly to the same alias with
uriandcache, avoiding a second wrapper alias while retaining provider
credentials. Cachedfallbackroutes remain available for multiple
authoritative providers.
Fixed
- Ruby gems for Apple silicon now use the generic
arm64-darwinplatform
instead of including the build runner's Darwin version. - Windows shared
secretspec-ffiinstalls now place the runtime DLL in the
documentedPREFIX/libruntime library directory. importwarns when a literal source uses convention naming but a provider
alias for the same storage container addresses active secrets differently
through areftemplate or scopedrefs. Import output also retains the
selected source alias, making alias-specific addressing visible without
changing literal-provider semantics.
(#312)- The error for a coordinate a provider does not support now points at
refs.<alias>and aliasreftemplates as well as at removing the
coordinate, so afieldwritten for one store no longer has to be dropped to
reach another store that organizes the secret differently.
(#266) - The Proton Pass provider works with
pass-cli2.2.4 and later, which removed
thepass-cli testsubcommand the provider ran to check the session before
every read and write. The check now triespass-cli infoand falls back to
pass-cli test, so a single build works acrosspass-clireleases that
disagree about which check exists. Apass-cliwith neither is reported as
incompatible with the SecretSpec release, instead of passing the CLI's usage
text through as the error.
(#279) - SOPS write-target previews consistently use canonical physical paths on macOS
and Windows, matching the files used for writes. - Passbolt now updates UUID-addressed resources outside a configured folder,
treats URI- and environment-selected forms of the same server as one import
destination, rejects malformed provider query parameters, and avoids
redundant resource listings during writes. - Cache entries now store their absolute expiration time, allowing SecretSpec
to remove an expired entry whenever it encounters one, including at an
address previously used by another project or profile. Changingmax_age
invalidates entries written under the previous policy. Fresh v2 entries remain
usable during migration, while foreign v2 entries remain untouched.
(#275) runpreserves non-UTF-8 environment values byte-for-byte when launching
child processes on Unix.- Provider-scoped references now compare provider-defaulted coordinates before
destructive imports, apply scoped address overrides before comparing stores,
and recognize missing file destinations reached through symlinked parents.
They also invalidate caches for every coordinate change without display-format
collisions and retain the attempted native location in audit events when a
provider read fails. Same-store import validation handles Windows provider
paths without treating separators as TOML escapes. - Profile overrides can switch between legacy
refand provider-scopedrefs
without retaining both inherited address models and failing validation. - JSON extraction from file-backed documents now handles Windows store paths
without treating path separators as TOML escapes. - SDK pkg-config setup now pins cargo-c's library and metadata install
directories, so Go, Ruby, and Haskell reliably discover
secretspec_ffi.pcacross environments. - The keyring provider no longer intermittently fails with a "No default store
has been set" error when resolving multiple secrets concurrently. - The SOPS provider no longer substitutes a second time into a rendered path
segment, so a project or profile literally named{profile}or{project}
resolves to the file you configured instead of a different one. - Invalid SOPS path templates are now rejected when loading serialized
provider configurations instead of being accepted without validation. - The LastPass provider now reports its full item template rather than only the
first segment. A multi-segment template such as
lastpass://Shared/{project}/{profile}/{key}used to be reported as plain
lastpass, which reads back as the defaultsecretspec/{project}/{profile}/{key}
template — a different folder — andlastpass://Work/TeamA/{key}read back as
the literal itemWork, one item for every secret. Templates that differ
below their first segment are now distinguished, so repointing a cached route
at a new template invalidates its cached values instead of serving the old
ones until they expire. Single-segment templates are unaffected; cached
entries for a multi-segment template refetch once, silently, on first run. - Provider fallback chains now reuse each provider and resolve independent
primary misses concurrently. Azure Key Vault providers also reuse their
client and serialize its initial challenge-based authentication, so chains
such asproviders = ["keyring", "akv"]no longer fetch every fallback in
series or launch separate Azure CLI processes for the same resolution. - Reusing a
Secretsinstance now refreshes fallback providers for each
resolution, so provider-side caches observe rotated values and providers use
the latest reason supplied withwith_reason.
Install secretspec 0.19.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/cachix/secretspec/releases/download/v0.19.0/secretspec-installer.sh | shDownload secretspec 0.19.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 |