Skip to content

AVP

v0.8.0 Security

This release includes 3 security fixes for security teams reviewing exposed deployments.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 3 known CVEs

Topics

agentic-ai vaultwarden

Affected surfaces

auth rbac breaking_upgrade

ReleasePort's take

Moderate signal
editorial:auto 8d

The GSM backend now enforces read‑only access and will deny startup if write permissions are granted.

Why it matters: If your deployment grants write permissions to the GSM backend, it will be blocked on start; ensure configurations use only read‑only mode (severity 90).

Summary

AI summary

Updates 0.8.0], 2026-07-18, Deprecated, and docs/adrs/ADR-0018-gcp-secret-manager-backend.md across a mixed release.

Changes in this release

Security Critical

GSM backend enforces read‑only; denies start if write permissions granted.

GSM backend enforces read‑only; denies start if write permissions granted.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

Notes host allowlist prevents confused‑deputy binding redirections on GCP.

Notes host allowlist prevents confused‑deputy binding redirections on GCP.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

Bare‑note shorthand now only matches valid hostnames, fixing silent binding breakage.

Bare‑note shorthand now only matches valid hostnames, fixing silent binding breakage.

Source: llm_adapter@2026-07-19

Confidence: high

Feature Medium

Adds Google Secret Manager backend (`backend.type: gsm`).

Adds Google Secret Manager backend (`backend.type: gsm`).

Source: llm_adapter@2026-07-19

Confidence: high

Feature Medium

Introduces Honeytoken tripwire and `honeytoken_triggered` audit event (audit contract v2 → v3).

Introduces Honeytoken tripwire and `honeytoken_triggered` audit event (audit contract v2 → v3).

Source: llm_adapter@2026-07-19

Confidence: high

Feature Medium

Adds `/healthz` liveness/readiness endpoint for orchestrator traffic control.

Adds `/healthz` liveness/readiness endpoint for orchestrator traffic control.

Source: llm_adapter@2026-07-19

Confidence: high

Feature Medium

Adds `avp-bindings` skill and Claude Code plugin packaging for AI‑assisted binding authoring.

Adds `avp-bindings` skill and Claude Code plugin packaging for AI‑assisted binding authoring.

Source: llm_adapter@2026-07-19

Confidence: high

Deprecation Low

Deprecates `agent_vault_proxy.bws_notes` module; use `agent_vault_proxy.notes_binding`.

Deprecates `agent_vault_proxy.bws_notes` module; use `agent_vault_proxy.notes_binding`.

Source: llm_adapter@2026-07-19

Confidence: high

Bugfix Medium

Fixes concurrency race in OAuth2 refresh write‑back path.

Fixes concurrency race in OAuth2 refresh write‑back path.

Source: llm_adapter@2026-07-19

Confidence: high

Bugfix Medium

Fixes case‑normalization bug in notes host allowlist matching.

Fixes case‑normalization bug in notes host allowlist matching.

Source: llm_adapter@2026-07-19

Confidence: high

Full changelog

[0.8.0], 2026-07-18

Added

  • Google Secret Manager backend (backend.type: gsm, ADR-0018). Third built-in backend after bws and static. Reads secret values from GSM with one REST access call per cache miss (stdlib urllib for the call; google-auth — a single first-party dep in a new gsm extra — mints/refreshes access tokens only, no gRPC SDK). Keyless by design: ADC + service-account impersonation, Workload Identity Federation, or plain user ADC — there is deliberately no key-file config field, and reject_ambient_key refuses a downloaded service-account key surfaced via ADC. Secure-by-default is a boot invariant, not a doc note: self_check: deny refuses to start under an over-broad identity (enumeration + project-level versions.access + write/admin testIamPermissions probes), avp gcp-setup grants only per-secret secretAccessor and hard-fails a project/folder/org bind, and _assert_in_scope refuses to fetch any name outside secret_prefix. Host binding lives at the vault via the avp-binding annotation (binding_source: gsm_notes, generalized to notes), reusing the backend-agnostic notes parser. New operator CLIs: avp gcp-setup and read-only avp doctor --probe-gcp. Hardened across four cross-vendor security review passes.
  • avp-bindings skill + Claude Code plugin packaging. The repo ships an Anthropic-format skill at skills/avp-bindings/ that walks an AI agent through authoring notes/annotation bindings (propose-only — it never sees or stores the secret). Packaged as a plugin via .claude-plugin/plugin.json + marketplace.json, so Claude Code users install it with /plugin marketplace add inflightsec/agent-vault-proxy then /plugin install avp@agent-vault-proxy; a manual ~/.claude/skills/ copy/symlink path is documented for other agents.
  • Honeytoken tripwire + honeytoken_triggered audit event (audit contract v2 → v3, ADR-0019). Any secrets: entry can set honeytoken: true to become a canary: plant its placeholder somewhere tempting and bind it to a trap host you control. Because the agent only ever holds the placeholder, the honeytoken's real value never enters its address space — but any use of that placeholder (injected, denied, scope-violated, or aimed at a non-bound host) makes the proxy emit a second honeytoken_triggered record immediately after the normal inject_decision, under the same synchronous fsync (G6 ordering preserved per record). Shipped off-box, one trigger anywhere in a fleet means that machine is being walked for credentials — the signal fires on intent, before any real value moves. The event carries only request_id, binding_name, dest_host, and underlying_reason — no secret material, header, body, or query string, per the §4.4 minimization contract. Emission is centralized in AuditWriter (keyed on the operator-flagged secret names, rebuilt per config reload), so it covers every decision path with no call site missed and is a no-op when no honeytoken is configured. Bumps AUDIT_CONTRACT_VERSION to 3; docs/architecture.md §4.4 documents the event; bindings.example.yaml carries a worked DECOY_AWS_PROD example. 10 tests.
  • /healthz liveness/readiness endpoint (roadmap: Observability). A plain-HTTP request through the proxy to the reserved sentinel host healthz.agent-vault-proxy.invalid at path /healthz is answered by the addon directly — never proxied upstream, emits no audit (health polling would otherwise flood the log). Returns 200 {"status": "ok"} once config, backend client, and audit writer are all live; 503 {"status": "starting"} before that, so an orchestrator holds traffic until AVP can actually broker. The body carries no version/build identifier — an unauthenticated endpoint should not hand out fingerprint/CVE-matching surface. The .invalid TLD (RFC 6761) can never collide with a real binding, and the gate is host and path — a real proxied request to /healthz on a bound host still injects normally. Intercepted before the destination allow-list so the probe isn't 403'd as unmatched. The Docker HEALTHCHECK now uses it (pure-Python, no curl/shell), replacing the bare-TCP probe that only proved the socket was open — not that AVP could broker. Prometheus metrics surface still pending (see docs/ROADMAP.md).

Security

  • Bare-note shorthand gated on hostname shape (live-incident fix). The ADR-0018 §4 Tier 0 bare-string shorthand (a note that is just api.example.com) treated ANY string note as a host. Real vaults carry free-text human descriptions in the note field ("HackerOne API identifier", "GCP project ID"); under binding_source: both each description became a garbage host binding that shadowed the secret's real bindings.yaml host — silently un-brokering the whole fleet (caught by the release smoke test on the first 0.8.0 deploy; the daemon was healthy but injecting nothing). The shorthand now fires only when the note is actually shaped like a hostname (≥2 dot-separated DNS labels, FQDN/IPv4/*.-wildcard); descriptive text returns NoBinding — no binding, not a garbage one. Explicit host: mappings are untouched. Regression tests feed the parser real-world description notes and pin both directions.
  • File-side notes host allowlist — annotations may only narrow, never add a host (ADR-0024). Closes the confused-deputy ADR-0018's fourth cross-vendor pass surfaced: on GCP, secretmanager.secrets.update (edit a secret's avp-binding annotation) and versions.access (read its value) are independently grantable, so a principal who can write the annotation but not read the secret can point it at a host they control — AVP then reads with its own identity and injects there, exfiltrating a value the attacker could never read directly. New opt-in top-level notes_host_allowlist bounds where notes/annotation-sourced bindings may route. Absent (the default) is byte-identical to prior behaviour — the zero-config North Star is untouched, pinned by a no-allowlist regression test. When set and binding_source is notes/both, a notes-supplied host outside the list has its binding entry dropped fail-closed at config-build, and a later request carrying that placeholder toward the dropped host is denied under the distinct host_not_in_allowlist audit reason (kept apart from invalid_binding_metadata). Annotations may still narrow methods/paths within an allowed host; file-secrets: hosts are trusted by definition and never rejected (including both-mode unions); multi-host fan-outs (ADR-0021) are judged per host; wildcard entries ride the existing allow_wildcard_hosts opt-in and a note can never broaden an exact entry. Source-agnostic — structural on GSM where the deputy exists, defense-in-depth on BWS. avp doctor --probe-gcp downgrades its annotation-trust WARN to OK once the allowlist is set.
  • ADR-0017 deferred hardening series closed (Amendment). All five items the v0.7.0 notes tracked as "hardening patch series remaining": (1) the SSRF guard's IP-literal short-circuit can no longer swallow its own block verdict — blocked literals raise without any DNS consultation; (2) token-exchange redirects are refused at the opener — any 3xx maps to token_endpoint_status:<code> with no retry and the Location target is never contacted (replaces the post-call geturl() check, which could only distrust a redirect after the redirected host had been visited); (3) refresh_token_rotated:pending is fsynced before the vault PUT (crash-window ordering — Oracle F2); (4) write-back value-precondition: an operator's manual mid-flight rotation is detected and never clobbered (new BackendWriteConflictError → outcome write_back_conflict; implements Oracle F3 as a stronger value variant, since the BWS SDK has no conditional PUT and revisionDate false-fires on note edits); (5) per-binding write_back_min_interval_seconds floor (default 60 s, 0 disables) bounds vault PUT pressure under forced-rotation storms (outcome write_back_rate_limited — Oracle F4). New refresh_token_rotated outcome values only — no new event types, no audit contract bump. ~20 new tests including an on-the-wire proof that the opener refuses redirects.
  • Concurrency audit + cross-vendor review hardening. A concurrency review of the oauth2_refresh write-back path closed a read-modify-write race on the per-binding write-back rate-limit bookkeeping — now serialized under a threading.Lock (_write_back_lock), so two in-flight rotations of the same binding can no longer both slip past the write_back_min_interval_seconds floor. A cross-vendor review pass separately caught a case-normalization bug: notes_host_allowlist entries are now lowercased at config-load, so a mixed-case allowlist entry can no longer silently fail to match the already-lowercased note host and drop a legitimately-allowed binding. New tests/test_concurrency_audit.py (five concurrency surfaces) and tests/test_addon_oauth2_concurrent.py (cold-start OAuth race).
  • Closed audit event-type set + emit() choke-point guard (ADR-0023). AUDIT_EVENT_TYPES in audit.py enumerates every event type the audit stream may carry; AuditWriter.emit() refuses (raises) any unlisted type. A new event type now requires a conscious edit to the closed set — the review point where it must prove no-secret-material and gain stateful no-leak coverage. Type-level guard; the per-type field allowlist is pinned in tests/test_audit_event_type_contract.py.
  • GSM read-only enforcement + annotation-trust advisory (ADR-0018, 4th cross-vendor pass). self_check now runs a third testIamPermissions probe for write/admin permissions (secretmanager.secrets.update / versions.add / secrets.delete) and refuses to start (deny) when AVP's identity holds any — AVP is a read-only broker, so a write grant is over-privileged (a compromised proxy could tamper with the vault or rewrite the routing annotations). Separately, avp doctor --probe-gcp now emits an annotation-trust WARN whenever binding_source is notes/both: because secretmanager.secrets.update (edit avp-binding) and versions.access (read the value) are independently grantable on GCP, a metadata-only writer can redirect an in-namespace secret to a host they control — a confused-deputy that abuses AVP's legitimate read access. Operators must lock annotation-write to the value-read trust tier. Both probes are best-effort (an inconclusive testIamPermissions never hard-blocks). 5 tests.

Deprecated

  • agent_vault_proxy.bws_notes module path. The note/annotation parser was renamed to agent_vault_proxy.notes_binding — it is backend-agnostic (BWS notes and GSM avp-binding annotations), so the bws_ prefix misled. The old path stays a re-export shim for back-compat but now emits a DeprecationWarning; import from notes_binding instead. Removal in a future release.

Breaking Changes

  • Renamed note/annotation parser module from `agent_vault_proxy.bws_notes` to `agent_vault_parser.notes_binding`; old path deprecated and will be removed.

Security Fixes

  • Bare‑note shorthand now requires hostname shape to prevent garbage host bindings.
  • Notes host allowlist (`notes_host_allowlist`) prevents confused‑deputy redirection of secrets via annotation edits.
  • GSM read‑only enforcement: `self_check` denies start if AVP identity has write/admin permissions on GCP Secret Manager.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track AVP

Get notified when new releases ship.

Sign up free

Related context

Beta — feedback welcome: [email protected]