Skip to content

Releases: jdx/fnox

v1.24.0: GitHub OAuth lease backend

06 May 19:29
Immutable release. Only release title and notes can be modified.
627fdec

Choose a tag to compare

A focused release that adds a new github-oauth lease backend for minting short-lived, user-attributed GitHub tokens via OAuth device flow — without distributing an app private key.

Added

github-oauth lease backend (#464) -- @jdx

A new lease type that creates GitHub App user access tokens using the OAuth device flow and injects them as GITHUB_TOKEN (or a custom env var) for the duration of fnox exec. It is the recommended option for local development and user-attributed gh / GitHub API usage where you want a short-lived token tied to the signed-in user instead of a long-lived PAT in fnox.toml.

[leases.github]
type = "github-oauth"
client_id = "Iv1.yourgithubappclientid"
scope = "repo read:org workflow"
duration = "8h"
fnox exec -- gh pr list

On first run, fnox prints a verification URL and user code, optionally opens the URL in your browser, and polls GitHub until you approve the device prompt. Subsequent runs reuse the cached token until it expires.

Highlights of the backend:

  • Only the GitHub App client ID is required — no app private key and no client secret, so the lease config can be checked in and shared across a team. (The existing github-app backend remains the right choice for installation tokens in CI.)
  • OS keyring caching of access and refresh tokens, keyed by client id + scope + endpoints. Disable with keyring_cache = false to force the device flow on every lease.
  • Refresh token reuse when GitHub issues one — refreshes happen transparently; if the refresh fails, fnox falls back to a fresh device flow.
  • Configurable env var via env_var (e.g. "GH_TOKEN") and configurable auth_base / api_base for GitHub Enterprise Server.
  • open_browser controls whether fnox tries to launch the verification URL automatically (uses open / xdg-open / start).

The supported-backends table in the leases guide is updated, and the github-app docs now point local/user-attributed workflows at github-oauth. See the GitHub OAuth lease docs for the full reference.

Full Changelog: v1.23.1...v1.24.0

💚 Sponsor fnox

fnox is maintained by @jdx under en.dev — a small independent studio building developer tooling like mise, aube, hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors.

If fnox is handling secrets or config for you or your team, please consider sponsoring at en.dev. Sponsorships are what let fnox stay independent and the project keep moving.

v1.23.1: Alpine binaries and fnox-core crate

02 May 19:15
Immutable release. Only release title and notes can be modified.
2899869

Choose a tag to compare

A small release that ships native musl binaries for Alpine users and splits the library half of fnox into its own fnox-core crate for downstream Rust consumers.

Added

musl Linux binaries (#452) -- @jdx

Releases now include x86_64-unknown-linux-musl and aarch64-unknown-linux-musl artifacts alongside the existing gnu builds. The previous glibc-linked binaries failed on Alpine with cannot execute: required file not found (missing libudev.so.1 and glibc-only symbols like __res_init) — even with gcompat installed. The musl builds are statically linked and run cleanly on alpine:3 and friends:

docker run --rm -v "$PWD:/work" alpine:3 sh -c \
  'cd /work && tar xzf fnox-*-x86_64-unknown-linux-musl.tar.gz && ./fnox --version'

Note: the fido2 provider is not compiled into musl builds (its ctap-hid-fido2 dependency doesn't build under musl). Alpine users needing hardware-key-style flows should use age, pass, or a cloud provider. The keychain provider compiles but, as on any headless Linux, requires a session bus at runtime.

Docs site favicons and web manifest (#448) -- @jdx

Adds a simplified vault-door favicon.svg plus favicon.ico, 16/32 PNGs, apple-touch-icon.png, Android Chrome icons, and a site.webmanifest for installable-PWA metadata.

Changed

fnox-core library crate (#458) -- @jdx

The repo is now a Cargo workspace, and the library half of fnox — every provider, the Provider trait, Config, SecretResolver, lease backends, settings, and the top-level Fnox API introduced in v1.22 — lives in a new fnox-core crate under crates/fnox-core/. The root fnox crate keeps the CLI-only pieces (commands, MCP server, TUI, shell integration, hook-env).

This is a pure refactor with no behavior change. Existing Rust consumers don't need to update imports: the binary crate's lib.rs re-exports every fnox-core module, so fnox::providers::*, fnox::config::*, fnox::Fnox, etc. continue to resolve. Projects that want a leaner dep tree can now depend on fnox-core directly instead.

Docs nav star badge (#447) -- @jdx

The GitHub link in the docs top-nav now reads ★ N instead of a bare number, and the count is actually populated on the live site — the deploy workflow now passes GITHUB_TOKEN to the VitePress build so stars.data.ts can hit the GitHub API at build time.

Full Changelog: v1.23.0...v1.23.1

💚 Sponsor fnox

fnox is maintained by @jdx under en.dev — a small independent studio building developer tooling like mise, aube, hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors.

If fnox is handling secrets or config for you or your team, please consider sponsoring at en.dev. Sponsorships are what let fnox stay independent and the project keep moving.

v1.23.0: Line selector for multiline secrets

26 Apr 20:12
Immutable release. Only release title and notes can be modified.
a9457e0

Choose a tag to compare

A small, focused release that adds a line selector for picking a single line out of a multiline secret — most useful for the pass convention of storing the password on line 1 and metadata (username, URL, etc.) on subsequent lines.

Added

Line selector for multiline secrets (#446) -- @fgrosse

Secrets now accept a 1-indexed line field that returns just the Nth line of the resolved value. This matches the pass show <entry> --clip=N convention and lets you expose multiple fields from a single pass entry as separate secrets:

[providers.pass]
type = "password-store"
prefix = "fnox/"

[secrets]
# `pass show fnox/database` returns:
#   <password>
#   <username>
DB_PASSWORD = { provider = "pass", value = "database", line = 1 }
DB_USERNAME = { provider = "pass", value = "database", line = 2 }

Details worth knowing:

  • line is mutually exclusive with json_path; using both on the same secret is an error.
  • Line splitting uses str::lines(), so \r\n endings are handled cleanly and a single trailing newline doesn't shift indices.
  • line = 0 and out-of-range values produce clear error messages (e.g. `line = 5` is out of range; secret has 2 line(s)).
  • Post-processing applies uniformly to provider, default, and env-var sources.
  • fnox sync and fnox reencrypt cache the raw provider value, not the post-processed view, so the selector stays a read-only projection.
  • fnox set still overwrites the entire entry — line is read-only. Edit individual lines of an existing entry with pass edit <entry>.

See the password-store provider docs for a full walkthrough.

New Contributors

Full Changelog: v1.22.0...v1.23.0

💚 Sponsor fnox

fnox is maintained by @jdx under en.dev — a small independent studio building developer tooling like mise, aube, hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors.

If fnox is handling secrets or config for you or your team, please consider sponsoring at en.dev. Sponsorships are what let fnox stay independent and the project keep moving.

v1.22.0: Library API and a sticky-provider fix for `fnox set`

26 Apr 16:19
Immutable release. Only release title and notes can be modified.
7b7798c

Choose a tag to compare

v1.22.0 introduces a top-level library API for embedding fnox in Rust applications, and fixes a sharp edge in fnox set that could turn an encrypted secret into plaintext.

Added

Top-level Fnox library API (#442) -- @bglusman

Downstream Rust consumers can now use fnox as a library in three lines instead of replicating the internals of GetCommand::run:

use fnox::Fnox;

let fnox = Fnox::discover()?;          // walks up + merges parent + local + global config
let value = fnox.get("MY_KEY").await?;
let names = fnox.list()?;

The new Fnox type lives in src/library.rs and is re-exported from the crate root. Highlights:

  • Fnox::discover() mirrors the binary's full config-discovery and merge chain via Config::load_smart, including the FNOX_PROFILE env var.
  • Fnox::open(path) loads an explicit config without the upward-search/merge behavior.
  • Fnox::with_profile("staging") builder for non-default profiles.
  • get() returns FnoxError::SecretNotFound with a populated "Did you mean…" suggestion, matching the CLI's UX so callers don't need to recompute it.
  • Fnox is cheap to clone (Config is held behind an Arc) and safe to hold across .await.

set() is intentionally not part of this first cut; it'll get its own design pass.

Fixed

fnox set no longer silently downgrades encrypted secrets to plaintext (#439) -- @rpendleton

When multiple providers were configured without a default_provider, running fnox set on an existing secret without --provider would write the new value as plaintext while leaving the original provider = "..." key in place. The next fnox get then failed trying to "decrypt" a value that was no longer encrypted.

fnox set now reuses the secret's existing provider before falling back to default_provider or plaintext, so updates stay encrypted and readable without having to pass --provider on every call:

fnox set --provider age MY_SECRET "original-value"   # encrypted with age
fnox set MY_SECRET "new-value"                       # still encrypted with age

Deterministic provider ordering in the generated schema (#432) -- @jdx

Within-category provider ordering in build/generate_providers.rs was inheriting fs::read_dir order, which is OS- and filesystem-dependent. That non-determinism flowed into docs/public/schema.json and caused autofix.ci to keep reshuffling 100+ lines between runs. A secondary sort by provider name fixes the churn; running fnox schema twice now produces byte-identical output.

Mobile docs banner layout (#437) -- @jdx

At <=640px the announcement banner now switches to a column layout with the close button pinned to the top-right corner, instead of cramming the message and "Read more" link onto one squeezed line.

Changed

  • Docs site nav now shows the current release version (read from Cargo.toml at build time) and a GitHub star count, matching the mise/aube docs (#443) -- @jdx
  • Added a dismissible cross-site announcement banner that fetches its config from jdx.dev/banner.json and respects the expires field (#434, #436) -- @jdx

New Contributors

Full Changelog: v1.21.0...v1.22.0

💚 Sponsor fnox

fnox is maintained by @jdx under en.dev — a small independent studio building developer tooling like mise, aube, hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors.

If fnox is handling secrets or config for you or your team, please consider sponsoring at en.dev. Sponsorships are what let fnox stay independent and the project keep moving.

v1.21.0: PowerShell integration and Windows fixes

21 Apr 01:58
Immutable release. Only release title and notes can be modified.
fd34317

Choose a tag to compare

v1.21.0 brings first-class PowerShell support for auto-loading secrets, plus two important fixes for Windows users.

Added

PowerShell integration (#421) -- @nbfritch

fnox now supports PowerShell (pwsh / powershell) alongside bash, zsh, fish, and Nushell for automatic secret loading. Add the following to your PowerShell profile to enable it:

(&fnox activate pwsh) | Out-String | Invoke-Expression

The integration hooks into the PowerShell prompt to run hook-env on each prompt, sets and unsets environment variables as you change directories, and prints the familiar fnox: +1 FOO / fnox: -1 FOO diff output. Tested on PowerShell 7.6 on macOS and Windows, as well as Windows PowerShell 5.1. See the Shell Integration guide for setup details.

Fixed

Windows: Nushell activation errors from backslashes in paths (#425) -- @john-trieu-nguyen

On Windows, fnox activate nu emitted paths with backslashes (e.g. C:\Users\john) inside Nushell double-quoted strings, which Nushell parses as escape sequences -- producing unrecognized escape after "\\" in string. Paths are now normalized to forward slashes so Nushell integration works out of the box on Windows.

Windows: Executable resolution for commands with extensions (#427) -- @john-trieu-nguyen

fnox exec -- npm install and similar commands previously failed on Windows because the Windows process API doesn't search PATHEXT the way a shell does, so npm (really npm.cmd) wouldn't be found. fnox exec, fnox edit, and the MCP server's exec tool now use which on Windows to resolve executables, matching shell behavior:

fnox exec -- npm install    # now works on Windows

Changed

  • Switched from an inlined clap-sort module to the published clap-sort crate (#409)

New Contributors

Full Changelog: v1.20.0...v1.21.0

v1.20.0: Doppler Provider and Sync Fix for json_path

04 Apr 15:48
Immutable release. Only release title and notes can be modified.
e313b27

Choose a tag to compare

v1.20.0 adds a new Doppler secrets manager provider and fixes a bug where fnox sync would corrupt secrets that use json_path extraction.

Added

Doppler secrets manager provider (#376) -- @natefaerber

fnox now supports Doppler as a secrets provider. The provider uses the Doppler CLI under the hood and supports project/config scoping, service token authentication, and efficient batch fetching via --json.

[providers]
app-prod = { type = "doppler", project = "my-app", config = "prd" }
app-dev  = { type = "doppler", project = "my-app", config = "dev" }

[secrets]
PROD_DB_URL = { provider = "app-prod", value = "DATABASE_URL" }
DEV_DB_URL  = { provider = "app-dev",  value = "DATABASE_URL" }

All configuration fields (project, config, token) are optional -- when omitted, the provider falls back to the Doppler CLI's own defaults (from doppler setup or environment variables like DOPPLER_TOKEN). Authentication works via interactive login, service tokens in config, or the DOPPLER_TOKEN / FNOX_DOPPLER_TOKEN environment variables.

You can add a Doppler provider interactively with:

fnox provider add my-doppler doppler

See the full Doppler provider documentation for setup instructions, CI/CD examples, and multi-environment patterns.

Fixed

fnox sync no longer corrupts secrets that use json_path (#371) -- @rpendleton

When syncing secrets that use json_path, the sync command was applying json_path extraction before caching the value. This meant the cached sync value contained only the extracted field (e.g. "admin") instead of the full raw secret (e.g. {"username":"admin","password":"secret123"}). On subsequent reads, json_path would be applied again to the already-extracted value, failing with "Failed to parse JSON secret".

The fix introduces SecretConfig::for_raw_resolve(), which strips post-processing fields (json_path, sync, default) before resolving. Both sync and reencrypt now use this method, ensuring raw provider values are always cached and future post-processing steps only need updating in one place.

New Contributors

Full Changelog: v1.19.0...v1.20.0

v1.19.0: Re-encrypt all the things

22 Mar 22:52
Immutable release. Only release title and notes can be modified.
2e81576

Choose a tag to compare

v1.19.0 adds a new fnox reencrypt command that makes it easy to re-encrypt all your secrets when encryption provider configuration changes -- for example, when adding or removing age recipients. This release also fixes a bug where fnox set -k would skip prompting for the secret value.

Added

fnox reencrypt subcommand (#365) -- @jdx

Previously, re-encrypting secrets after changing recipients required a tedious manual loop of fnox get and fnox set for each secret. The new fnox reencrypt command handles this in one step: it decrypts matching secrets and re-encrypts them with the current provider configuration, writing the updated ciphertext back to the correct source config file.

# Re-encrypt all age secrets
fnox reencrypt -p age

# Preview what would be re-encrypted
fnox reencrypt -p age --dry-run

# Re-encrypt specific keys
fnox reencrypt MY_SECRET OTHER_SECRET

# Filter by regex pattern
fnox reencrypt --filter "^DB_"

# Skip the confirmation prompt
fnox reencrypt -p age -f

The command correctly handles multi-line secrets, writes back to the original source file (including distinguishing root [secrets] from [profiles.X.secrets]), clears stale sync caches, and scrubs decrypted plaintext from the process environment after re-encryption. Only secrets backed by encryption-capable providers are eligible.

Fixed

fnox set -k now correctly prompts for the secret value (#367) -- @jdx

When using the -k / --key-name flag with fnox set, the command incorrectly treated it as a metadata-only operation and skipped prompting for the secret value. It also wrote the key name itself as the stored config value, bypassing the encryption provider entirely. Now -k works as expected: the secret value is read from stdin, a command-line argument, or an interactive prompt, and is properly encrypted and stored.

# These now work correctly
echo "my-secret" | fnox set -p age -k custom-key-name MY_SECRET
fnox set -p age -k custom-key-name MY_SECRET "my-secret"

Full Changelog: v1.18.0...v1.19.0

v1.18.0: MCP Security Hardening and Sync Local File Output

13 Mar 15:18
Immutable release. Only release title and notes can be modified.
d2b7602

Choose a tag to compare

v1.18.0 strengthens MCP server security with automatic output redaction and a secret allowlist, adds a --local-file option to fnox sync for keeping sync caches out of your committed config, and fixes auth prompt handling in batch providers. The YubiKey provider also no longer requires libusb to be installed just to start the binary.

Highlights

  • MCP output redaction -- The exec tool now automatically replaces resolved secret values with [REDACTED] in stdout/stderr before returning output to the agent, closing a gap where agents could exfiltrate secrets via commands like printenv.
  • MCP secret allowlist -- A new mcp.secrets config option restricts which secrets the MCP server exposes to AI agents, with dependency-aware warnings at startup.
  • fnox sync --local-file -- Sync overrides can now be written to fnox.local.toml (gitignored) instead of the main config file, keeping your committed config clean.
  • YubiKey dynamic libusb loading -- The binary no longer hard-links libusb, so it starts normally on systems without libusb installed. Users get a clear error with install instructions only when they actually use the YubiKey provider.

Added

MCP exec output redaction (#357) -- @jdx

The MCP exec tool now scans stdout/stderr for resolved secret values and replaces them with [REDACTED] before returning output to the agent. This prevents agents from exfiltrating secrets via commands like printenv or echo $SECRET. Redaction uses Aho-Corasick leftmost-longest matching for correctness and is enabled by default. To disable (not recommended):

[mcp]
redact_output = false

MCP secret allowlist (#358) -- @jdx

A new mcp.secrets config option restricts which secrets the MCP server resolves and exposes. Unlisted secrets are never resolved (avoiding unnecessary auth prompts) and are invisible to both get_secret and exec. At startup, fnox warns if the allowlist contains unknown names or if an allowlisted secret depends on another secret not in the list.

[mcp]
secrets = ["GITHUB_TOKEN", "NPM_TOKEN"]  # only these are available to the agent

When omitted, all profile secrets are available (backward compatible).

fnox sync --local-file output target (#317) -- @florian-lackner365

fnox sync now accepts a --local-file flag that writes sync overrides to the local override file (fnox.local.toml or .fnox.local.toml) next to your config file, instead of modifying the main config. This keeps encrypted sync caches out of version control. The flag requires the config filename to be fnox.toml or .fnox.toml (other filenames are rejected) and conflicts with --global.

fnox sync -p age --local-file
# writes to fnox.local.toml (add to .gitignore)

Fixed

Auth prompts now work in batch providers (#349) -- @johnpyp

When a batch provider (e.g. AWS KMS resolving multiple secrets at once) returned an auth error, the auth_command fallback was not triggered -- the secrets were silently skipped. Batch resolution now detects auth errors in the results, runs the configured auth command (e.g. aws sso login), and retries the batch.

Changed

YubiKey provider loads libusb dynamically (#348) -- @jdx

The yubico_manager crate has been replaced with a minimal reimplementation that loads libusb at runtime via libloading. Previously, libusb was linked at build time, which caused the binary to crash on startup (dyld errors on macOS) for users who did not have Homebrew libusb installed -- even if they never used the YubiKey provider. Now the binary starts normally on all systems, and users who try to use the YubiKey provider without libusb get a clear error with platform-specific install instructions.

New Contributors

Full Changelog: v1.17.0...v1.18.0

v1.17.0: MCP Server, Cloudflare and GitHub App Leases, XDG Compliance

09 Mar 05:26
Immutable release. Only release title and notes can be modified.
0bf0391

Choose a tag to compare

v1.17.0 introduces an MCP server for AI agent secret access, two new lease backends (Cloudflare and GitHub App), and the ability to resolve leased credentials from fnox get. It also brings XDG-compliant directory locations, improved signal handling in fnox exec, and several UX fixes across the TUI, FIDO2, and fnox set.

Highlights

  • MCP server for AI agents -- fnox mcp starts a session-scoped secret broker over stdio, letting AI agents like Claude Code access secrets without having them directly in the environment.
  • Cloudflare and GitHub App lease backends -- Create short-lived, scoped Cloudflare API tokens and GitHub App installation tokens with automatic expiry and revocation support.
  • fnox get resolves leases -- Requesting a key that a lease backend produces (e.g. fnox get AWS_ACCESS_KEY_ID) now resolves the lease automatically, with caching.
  • XDG-compliant directories -- Lease ledger storage now follows the XDG spec, moving from ~/.config/fnox/leases/ to ~/.local/state/fnox/leases/ with automatic migration.

Added

MCP server for secret-gated AI agent access (#343) -- @jdx

The new fnox mcp command starts a Model Context Protocol server over stdio with two tools: get_secret (retrieve a secret by name) and exec (run a command with secrets injected as env vars). Secrets are batch-resolved on first access and cached in memory for the session. Tools can be selectively enabled via config:

[mcp]
tools = ["get_secret", "exec"]  # default: both enabled

Configure in .claude/settings.json:

{
  "mcpServers": {
    "fnox": {
      "command": "fnox",
      "args": ["mcp"]
    }
  }
}

Cloudflare API token lease backend (#335) -- @jdx

A new cloudflare lease backend creates short-lived, scoped Cloudflare API tokens. A parent token with API Tokens: Edit permission creates child tokens that automatically expire. Supports user-owned and account-owned tokens, explicit policies or parent-inherited policies, and configurable duration up to 24 hours.

[leases.cf]
type = "cloudflare"
account_id = "abc123def456"
duration = "1h"

[[leases.cf.policies]]
effect = "allow"
resources = { "com.cloudflare.api.account.{account_id}" = "*" }

[[leases.cf.policies.permission_groups]]
id = "c8fed203ed3043cba015a93ad1616f1f"
name = "Zone Read"

GitHub App installation token lease backend (#342) -- @jdx

A new github-app lease backend creates short-lived GitHub installation access tokens (1 hour max, GitHub's hard limit). Supports scoping to specific permissions and repositories, GitHub Enterprise via api_base, and token revocation via the GitHub API.

[leases.github]
type = "github-app"
app_id = "12345"
installation_id = "67890"
private_key_file = "~/.config/fnox/github-app.pem"

[leases.github.permissions]
contents = "read"
pull_requests = "write"

fnox get resolves leased credentials (#338) -- @jdx

fnox get now checks if the requested key is produced by a configured lease backend before falling back to provider secret resolution. For example, fnox get AWS_ACCESS_KEY_ID will resolve through the AWS STS lease backend (with caching) if one is configured.

fnox lease defaults to creating all leases (#337) -- @jdx

fnox lease create no longer requires a backend name -- omitting it (or passing --all) creates leases for all configured backends sequentially. Secrets are resolved once upfront and shared across backends. fnox lease with no subcommand also defaults to lease create --all.

FIDO2 PIN masking (#334) -- @jdx

FIDO2 PIN prompts now mask input with asterisks during typing, preventing shoulder-surfing.

fnox init -f (#329) -- @jdx

Added -f as a short alias for --force on the init command, consistent with import and sync.

Fixed

XDG-compliant directory locations (#336) -- @jdx

Lease ledger files are now stored under ~/.local/state/fnox/leases/ (or $XDG_STATE_HOME/fnox/leases/), following the XDG Base Directory spec. Config resolution now honors $XDG_CONFIG_HOME. Existing ledger files are automatically migrated on first access. A new FNOX_STATE_DIR env var overrides the state directory.

fnox exec signal handling and silent exit (#339) -- @jdx

fnox exec now forwards SIGINT and SIGTERM to the child process so Ctrl-C and kill reach it properly. On subprocess failure, fnox exits silently with the child's exit code (128+signal for signal deaths) instead of printing a noisy error message. Temp files from as_file secrets are now properly cleaned up via Rust destructors.

fnox set writes to the correct config file (#331) -- @jdx

fnox set now writes to the lowest-priority existing config file in the current directory instead of always targeting fnox.toml. If only fnox.local.toml exists, secrets are written there. If a non-default profile is active and a profile-specific file exists (e.g. fnox.staging.toml), secrets are written there.

TUI skips interactive-auth providers (#333) -- @jdx

fnox tui now skips FIDO2 and YubiKey providers that require physical interaction, preventing display corruption from provider stderr output and input prompts. An error message directs users to fnox exec instead.

Removed duplicate FIDO2 touch prompt (#332) -- @jdx

Removed the redundant "Touch your FIDO2 key..." message -- the underlying library already prints its own touch prompt.

Breaking Changes

Lease ledger location moved -- Lease ledger files have moved from ~/.config/fnox/leases/ to ~/.local/state/fnox/leases/. Existing files are migrated automatically, but if you have scripts that reference the old path directly, update them to use ~/.local/state/fnox/leases/ or the FNOX_STATE_DIR env var.

fnox exec exit behavior changed -- fnox exec no longer prints an error message or returns a CommandExitFailed error when the subprocess fails. It exits silently with the child's exit code. If you were parsing fnox's error output to detect subprocess failures, check the exit code instead.

fnox lease create backend name is now optional -- Running fnox lease create without arguments now creates all configured leases instead of printing a usage error. Scripts that relied on the missing-argument error should be updated.

Full Changelog: v1.16.1...v1.17.0

v1.16.1: Encryption failures are now hard errors

08 Mar 01:55
Immutable release. Only release title and notes can be modified.
6166e40

Choose a tag to compare

This patch release fixes a security-relevant bug where fnox set silently stored secrets as plaintext when an encryption provider failed. It also adds custom endpoint support for all three AWS providers.

Fixed

fnox set now fails on encryption errors (#324) -- @jdx

Previously, fnox set caught encryption errors from any provider (age, AWS KMS, Azure KMS, GCP KMS, FIDO2, YubiKey) and silently fell back to storing the secret as plaintext. This meant a misconfigured or unreachable encryption provider would result in unencrypted secrets in your config file with only a warning in the logs.

Encryption failures are now hard errors -- fnox set will exit with a non-zero status and an error message instead of quietly storing plaintext.

Fixed Linux cross-compilation (#326) -- @jdx

Cross-compiled Linux builds (x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu) were failing due to a missing libudev-dev system dependency required by the hidapi crate. A Cross.toml configuration now ensures the dependency is installed in the cross-compilation Docker containers.

Added

Custom endpoint for AWS providers (#324) -- @jdx

The AWS KMS (aws-kms), Secrets Manager (aws-sm), and Parameter Store (aws-ps) providers now accept an optional endpoint field. This lets you point them at LocalStack, MinIO, or any other AWS-compatible API endpoint. Add it to your provider config like so:

[providers.kms]
type = "aws-kms"
key_id = "alias/my-key"
region = "us-east-1"
endpoint = "<your-custom-endpoint-url>"

Breaking Changes

If you previously relied on fnox set silently falling back to plaintext when encryption failed, this behavior is removed. Encryption errors now cause the command to fail. Review any scripts or CI pipelines that call fnox set with encryption providers to ensure the provider is correctly configured and reachable.

Full Changelog: v1.16.0...v1.16.1