Skip to content

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 02 Jul 12:04

Security-hardening release following a deep review of the data path. The only wire
change is the sentinel format (⟦S:TYPE·id·tag⟧); multi-node clusters must set
sessions.encryption_key (see below).

Security — sentinel authentication & masking coverage

  • Authenticated sentinels — every sentinel now carries a per-vault keyed MAC
    tag (⟦S:TYPE·id·tag⟧, HMAC-SHA256). Rehydration resolves an id only if its tag
    matches, so a hostile/compromised upstream can no longer forge or blindly
    enumerate sentinels (⟦S·0⟧, ⟦S·1⟧, …) to read a session vault. Cross-node
    session tag keys derive from sessions.encryption_key (set it on clusters).
  • Enforce mode fails closed on unparseable JSON — a JSON-typed request body
    that doesn't parse is rejected (422) instead of forwarded unmasked.
  • Opt-in comprehensive scanningscan_paths: ["**"] (and stream_paths)
    scans/rehydrates every string leaf, for deployments that want maximum coverage
    over provider-aware minimalism.

Security — SSRF, isolation, DoS, and fail-closed

  • Upstream redirects are no longer followed (proxy, interception, and Vault
    clients). Prevents SSRF to internal/metadata endpoints and stops a malicious
    upstream from getting a rehydrated (secret-bearing) response via a redirect; the
    Vault connector can no longer leak X-Vault-Token to a redirect target.
  • Session vaults are tenant-isolated by an unforgeable namespace scheme — a
    flat-auth (non-tenant) client can no longer craft a session key that collides
    with a tenant's vault.
  • CONNECT-proxy tunnels refuse loopback / link-local targets (blocks the cloud
    metadata endpoint 169.254.169.254 and localhost pivots) and connect to the
    exact vetted IP (no DNS-rebind window).
  • Certificate minting is restricted to configured interception hosts (+ a cache
    cap), preventing a DoS from unbounded key-generation on arbitrary SNI values.
  • Audit and transaction logs are created 0600 (owner-only) on Unix — the
    transaction log can hold original content in dry-run mode.
  • Proxy auth compares fixed-length SHA-256 digests in constant time, removing a
    key-length timing side channel.
  • Vault dedup is keyed by the exact original bytes, not a truncated 64-bit
    hash — two distinct secrets can no longer be conflated into one sentinel (which
    would mis-rehydrate one secret as another in a shared session vault). All
    plaintext copies (forward keys + reverse values) are zeroized on drop.
  • Per-leaf streaming rehydration: each response content leaf (e.g. each
    choices[i].delta.content) gets its own rehydrator, so a partial sentinel's
    carry can no longer bleed between leaves and leak an un-rehydrated sentinel when
    n > 1 (multiple choices / content items) with a sentinel split across events.
  • Id-space exhaustion is fail-safe: a session vault never mints an id past its
    node's range (which would rehydrate to the wrong secret across nodes) — on
    exhaustion the value is masked with a reserved non-reversible id.
  • Secret-source loading fails closed: if a configured source (file/Vault)
    errors, reload keeps the previous good config and startup refuses, rather than
    silently running with reduced masking coverage.
  • Loud warning when sessions.node_id is unset with the Redis backend (random
    fallback can collide across nodes); Redis read failures are logged (not silently
    treated as an empty session); masking.ttl parsing no longer overflows.