Release Notes
Added
- Audit logging for secret access, on by default. Every secret read and write,
from both the CLI and the Rust SDK, is appended to a local per-user log as JSON
Lines. Only metadata is recorded (secret names, the serving provider with any
embedded credentials redacted, outcome, reason, and actor including a detected
coding agent); secret values are never written. Each operation is recorded once:
getandsetper secret,checkas a single event,runwhen the child
process starts, andimportper copied secret. Auditing never blocks secret
access; if it cannot write the log it warns on stderr and continues. The log is
a single file capped at 1 MiB. It is configured per machine via the[audit]
table in~/.config/secretspec/config.toml(not the project's
secretspec.toml), so a cloned repository cannot redirect or silence it. The
newsecretspec auditcommand reads the log, with--project,--action,
--tail/-n, and--jsonfilters. See
Audit Logging for details. --reasonCLI flag (andSECRETSPEC_REASONenv var) records a human-readable
reason for a session's secret access, forwarded to providers that support audit
logging.SECRETSPEC_REASONis honored across the SDK/library too: it is resolved
bySecrets::load/load_from(sosecretspec-derive-generated code and other
library callers can satisfy therequire_reasonpolicy and supply an audit reason
without code changes), andSecrets::with_reason(...)sets it explicitly, taking
precedence. Thesecretspec-derive-generated typed builder also gains a
with_reason(...)method, so SDK callers can satisfyrequire_reasonin code
(not only via the env var). Blank or whitespace-only reasons are ignored so they
cannot satisfy the policy. Backed by a newProvider::set_reasontrait method
(default no-op).[project] require_reasonpolicy insecretspec.toml, controlling when secret
access must supply an explicit reason. Accepts"agents"(the default — require
a reason only when an AI agent is detected),true(require it from every
caller), orfalse(never). Agent detection is delegated to the
detect-coding-agentcrate (Claude Code, Cursor, Codex, Gemini CLI, Copilot,
...), plus aSECRETSPEC_AGENTopt-in for harnesses it does not recognize.
Because the tool enforces it and it is checked into the repo, the policy applies
uniformly and cannot be bypassed by an individual tool's configuration. An invalid
require_reasonvalue is rejected at config-parse time rather than silently
falling back to the default. The policy is inherited throughextends: a shared
base config'srequire_reasonapplies to every config that extends it, unless the
child sets its own.
Note: the default"agents"means AI agents must now pass a reason out of
the box.bwsprovider now accepts an optional server base in the URI
(bws://[server-base@]project-uuid) to target EU cloud or self hosted
Bitwarden instances. When set, the identity and API endpoints are derived as
https://<server-base>/identityandhttps://<server-base>/api; omitting it
keeps thebitwarden.comUS cloud default.
Changed
- Minimum supported Rust version raised to 1.92 (required by the
detect-coding-agentdependency). The devenv toolchain is pinned accordingly.
Fixed
- Proton Pass provider now works with
pass-cli>= 2.1.0 agent sessions. Since
2.1.0, audited item operations (item view,item create,item delete)
fail unlessPROTON_PASS_AGENT_REASONis set, which made existing secrets
appear missing under an agent session. The provider now sets this variable on
everypass-cliinvocation. The reason is resolved as--reason/with_reason,
thenPROTON_PASS_AGENT_REASON, then a secretspec-versioned default
(secretspec/<version> (https://secretspec.dev)); each source is normalized first,
so a blank reason falls through to the next rather than masking it. It is ignored by
older releases and non-agent sessions. secretspec initnow serializes the generatedsecretspec.tomlwith
toml_editinstead of hand-interpolating strings. This fixes several cases
that previously produced TOML that could not be parsed back: a project name,
secret description, or default value containing a double-quote, backslash,
control character (including U+007F), or newline; a secret name containing a
dot (e.g.FOO.BAR, which dotenvy accepts and which silently collapsed to a
nested key); and a configuredproject.extends, which was dropped entirely.
Output is now also deterministically ordered.secretspec initno longer defines a conflicting-fshort flag for
--from;-fis reserved for the global--fileoption. The duplicate
short flag madesecretspec initpanic in debug builds and was ambiguous in
release builds.
Install secretspec 0.12.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/cachix/secretspec/releases/download/v0.12.0/secretspec-installer.sh | shDownload secretspec 0.12.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 |