Skip to content

14.4.0

Latest

Choose a tag to compare

@jhaals jhaals released this 04 Jul 19:32
f3b664d

Machine-to-machine authentication for create endpoints

Backend services can now create secrets, files, and secret requests when --require-auth is enabled without going through the interactive OIDC login. A new --api-token flag (or API_TOKEN env var) accepts one or more name:secret pairs; requests authenticate via Authorization: Bearer <secret> and are matched in constant time. Token secrets are hashed once at startup and only the digest is kept in memory.

  • Tokens gate creation only (/create/secret, /create/file, /request); retrieving auth-protected secrets still requires a session
  • Service identities are attributed in audit logs as service:<name> and bypass --oidc-allowed-domains, since there's no email to check
  • Startup validation rejects malformed tokens, secrets shorter than 16 characters, duplicate names, and any --api-token set without --require-auth

Fix S3 file store on Cloudflare R2

File uploads to Cloudflare R2 failed outright: R2 rejects PutObject requests carrying x-amz-tagging with a 501, and the file store tagged every object with its expiry. The tag was redundant — expiry was already written to the Expires header, which R2 does support — so tagging is dropped and the cleanup goroutine now reads expiry via HeadObject instead. Behavior against AWS S3 is unchanged.

Skip server lookups for terminal requests and receipts

Secret requests and read receipts now resolve terminal states from local storage instead of polling the server:

  • Expired or already-fulfilled requests are read from the local cache; the navbar badge counts cached-fulfilled requests directly and only polls the ones still pending
  • The receipts list skips lookups for receipts already marked viewed or past expiry, and the result-page panel stops polling on expiry as well as on view

This cuts recurring 404/no-op requests for state that can no longer change.

Honor LOG_LEVEL and TRUSTED_PROXIES environment variables

Two configuration options documented in docs/server-options.md were silently ignored when set via environment variable:

  • LOG_LEVEL was only applied when passed as the --log-level fits level through Viper so the flag, env var, and config file allwork
  • TRUSTED_PROXIES (and OIDC_ALLOWED_DOMAINS) are list settings that Viper only comma-splits when passed as a flag — via env var the whole value came through as one entry, so TRUSTED_PROXIES=a,b never matched. A comma-awansistently regardless of source

Secret requests: atomic lifecycle transitions in multi-instance deployments

Secret request state changes (fulfillment, key rotation) are now enforced atomically by the storage backend, using transactions in Redis and compare-and-swap in Memcached.

Previously, these transitions were only serialized within a single server process. In deployments running multiple yopass instances against a shared Redis or Memcached backend, concurrent operations on the same request could act on stale state:

  • Two simultaneous fulfillments could both be accepted, with the second silently overwriting the first responder's encrypted secret.
  • A fulfillment racing a revocation could re-store the deleted record, leaving a revoked request retrievable with its management token until it expired.

Single-instance deployments were not affected. Exploitation required possession of the request link (an authorized responder by design) and winning a very narrow timing window, so practical impact is limited, but revocation and single-fulfillment are guarantees this feature makes, and they now hold regardless of instance count.