Skip to content

v9.9.0 — per-user audit attribution unified + session-override hardening

Choose a tag to compare

@saurabhjain1592 saurabhjain1592 released this 11 Jul 13:38
· 31 commits to main since this release
e760549

[9.9.0] - 2026-07-11 (per-user audit attribution unified + session-override forgery hardening)

Security + correctness. v9.9.0 unifies per-user audit attribution across all four governance planes behind an opt-in trust gate (AXONFLOW_TRUST_IDENTITY_HEADERS, default off), and closes a forged-identity session-override hijack — a deny→allow flip in which one governed user could apply another user's active session override — across the request-plane governance and workflow endpoints. No database migration. Behavior change: the planes that previously honored client-asserted identity headers unconditionally now ignore them unless the gate is on — set AXONFLOW_TRUST_IDENTITY_HEADERS=true on the agent (after confirming your identity source is trusted) to retain per-user attribution.

Fixed

  • Per-user audit attribution unified across all four governance planes, behind a trust gate. (Community) The client-asserted X-User-Email / X-Session-Id / X-User-ID headers were honored on only two of the four governance planes — MCP check-input and MCP-server tools/call read them unconditionally, while /api/v1/decide and MCP check-output ignored them entirely. The split had two consequences: PEPs that front many principals behind one org:license credential (the Claude Desktop proxy calls only decide + check-output) silently lost per-user attribution — every action attributed to the fleet service identity — and on the two planes that did read the headers, ANY governed caller could forge another principal's audit identity, including hijacking another user's active ADR-044 session override (a deny→allow flip keyed on the unvalidated header). All four planes now resolve the headers through one shared trust gate, AXONFLOW_TRUST_IDENTITY_HEADERS (default off; only the exact string true opts in — the same contract as the 9.8.0 gateway adapters): with the gate on, the headers attribute audit_logs.user_email / session_id on every plane, and per-user features (ADR-044 session overrides, user-scoped dynamic policies) key on that trusted identity — a forged header can never influence a verdict, authz decision, policy selection, or tenant/org resolution; with the gate off, the headers are ignored everywhere and attribution falls back to the validated identity, with a once-per-process detection warning when a request carries identity headers so an operator never silently loses attribution. Additionally, no platform-synthesized SHARED identity — the mcp-client:<client-id> pseudo-identity, the <client-id>@axonflow.local / unknown@axonflow.local service fallbacks, the internal-service and community-SaaS evaluator identities, or the community local-dev identity when asserted outside community mode — can create, be offered, or apply an ADR-044 session override on any plane; a shared identity's override would flip a deny for every caller on the client. And every orchestrator ingress that keys an ADR-044 override apply — override-create, the WCP step-gate, the MAP confirm-mode plan-execute and plan-resume, and both workflow checkpoint-resume paths (which re-evaluate a step under the checkpoint's stored actor identity) — now requires the Agent gateway's HMAC proxy token, so a caller reaching the orchestrator directly cannot forge the override identity (Community mode is exempt, matching the existing audit-tool-call enforcement). The MAP execute path additionally derives the checkpoint's actor email from the trust-gated X-User-Email header rather than the request body, closing a channel the header gate does not cover. Complementing that, the Agent proxy now trust-gates the per-user identity headers (X-User-Email / X-User-ID / X-Session-Id) on every proxied route rather than a per-prefix allowlist: with the gate off (default) a forged per-user identity is stripped before it can reach any orchestrator route, and the auth-derived tenant/org headers and the proxy-auth token are never touched. Advertised as the identity_header_attribution capability. Upgrade note: deployments relying on plugin-supplied identity headers must set AXONFLOW_TRUST_IDENTITY_HEADERS=true on the agent after confirming their identity source is trusted (MDM-managed plugin fleet, desktop proxy, gateway jwtAuth) — until then, per-user attribution, the session-summary/Claude-Code dashboards' per-session drill-down (session_id stays NULL on new rows), and per-user session overrides all fall back to the client-scoped identity. The previous always-trust behavior was a forgery exposure and is deliberately not preserved.

Full notes: https://docs.getaxonflow.com/docs/releases/v9-9-0