Hi team,
I'd like to report what appears to be a missing channel assignment in command/agent.go that prevents the auto-auth self-healing feature from working when Vault Agent is used with the caching/proxy listener. I wanted to check with you whether this is intentional (given Agent's API proxy is deprecated in favor of Vault Proxy) or if it was an oversight.
Summary
The auto-auth self-healing feature (introduced in v1.17.0 via #26307) correctly wires the invalidTokenErrCh and authInProgress channels in command/proxy.go, but the equivalent assignment is missing in command/agent.go. This means the self-healing works for vault proxy but not for vault agent when using the cache/listener.
Code References (v1.21.4)
In command/proxy.go, the local variables are reassigned to the auth handler's channels after ah is created:
https://github.com/hashicorp/vault/blob/v1.21.4/command/proxy.go#L578-L579
authInProgress = ah.AuthInProgress
invalidTokenErrCh = ah.InvalidToken
In command/agent.go, the same variables are created at:
https://github.com/hashicorp/vault/blob/v1.21.4/command/agent.go#L552-L553
authInProgress := &atomic.Bool{}
invalidTokenErrCh := make(chan error)
But they are never reassigned to ah.AuthInProgress / ah.InvalidToken. They are passed directly to ProxyHandler as orphaned local variables:
https://github.com/hashicorp/vault/blob/v1.21.4/command/agent.go#L685-L687
For reference, the auth handler creates its own buffered channel and atomic bool that are meant to be used:
https://github.com/hashicorp/vault/blob/v1.21.4/command/agentproxyshared/auth/auth.go#L99-L101
InvalidToken: make(chan error, 1), // buffered
AuthInProgress: &atomic.Bool{},
And the auth handler listens on ah.InvalidToken to trigger re-auth:
https://github.com/hashicorp/vault/blob/v1.21.4/command/agentproxyshared/auth/auth.go#L607
case <-ah.InvalidToken:
ah.logger.Info("invalid token found, re-authenticating")
break LifetimeWatcherLoop
Observed Behavior
When running vault agent (v1.17.3 tested, also verified in v1.21.4 source) with auto_auth + cache + listener:
- Revoke the agent's token on the server side
- Send a request through the agent's cache listener
- Agent logs:
"proxy received an invalid token error" (from handler.go#L77)
- But the agent never logs
"invalid token found, re-authenticating" (from auth.go#L608)
- The client request hangs until timeout — no HTTP response is returned
The hang occurs because invalidTokenErrCh is an unbuffered channel with no reader. The send at handler.go#L81 blocks the HTTP handler goroutine, preventing the response from being flushed.
Expected Behavior
Same as vault proxy — after detecting an invalid token, the agent should trigger re-authentication and retry with a fresh token.
Additional Impact
- Each request that hits this path creates a blocked goroutine (~4-8 KB) that is never cleaned up, leading to a small but cumulative resource leak under sustained retry load
- The
authInProgress variable is also not wired (agent.go L552), so the handler always reads false and always attempts the channel send, even during actual re-authentication
- Switching to
vault proxy is not always feasible — the Vault Agent Injector for Kubernetes only supports injecting vault agent, not vault proxy (see vault-k8s #495)
Affected Versions
v1.17.0 through v1.21.4, and current main branch (v2.0.2).
Possible Fix
Add the two missing assignments in command/agent.go, after ah is created (around line 600), matching what command/proxy.go already does:
authInProgress = ah.AuthInProgress
invalidTokenErrCh = ah.InvalidToken
Thank you for your time, and for the great work on the self-healing feature.
Hi team,
I'd like to report what appears to be a missing channel assignment in
command/agent.gothat prevents the auto-auth self-healing feature from working when Vault Agent is used with the caching/proxy listener. I wanted to check with you whether this is intentional (given Agent's API proxy is deprecated in favor of Vault Proxy) or if it was an oversight.Summary
The auto-auth self-healing feature (introduced in v1.17.0 via #26307) correctly wires the
invalidTokenErrChandauthInProgresschannels incommand/proxy.go, but the equivalent assignment is missing incommand/agent.go. This means the self-healing works forvault proxybut not forvault agentwhen using the cache/listener.Code References (v1.21.4)
In
command/proxy.go, the local variables are reassigned to the auth handler's channels afterahis created:https://github.com/hashicorp/vault/blob/v1.21.4/command/proxy.go#L578-L579
In
command/agent.go, the same variables are created at:https://github.com/hashicorp/vault/blob/v1.21.4/command/agent.go#L552-L553
But they are never reassigned to
ah.AuthInProgress/ah.InvalidToken. They are passed directly toProxyHandleras orphaned local variables:https://github.com/hashicorp/vault/blob/v1.21.4/command/agent.go#L685-L687
For reference, the auth handler creates its own buffered channel and atomic bool that are meant to be used:
https://github.com/hashicorp/vault/blob/v1.21.4/command/agentproxyshared/auth/auth.go#L99-L101
And the auth handler listens on
ah.InvalidTokento trigger re-auth:https://github.com/hashicorp/vault/blob/v1.21.4/command/agentproxyshared/auth/auth.go#L607
Observed Behavior
When running
vault agent(v1.17.3 tested, also verified in v1.21.4 source) withauto_auth+cache+listener:"proxy received an invalid token error"(from handler.go#L77)"invalid token found, re-authenticating"(from auth.go#L608)The hang occurs because
invalidTokenErrChis an unbuffered channel with no reader. The send at handler.go#L81 blocks the HTTP handler goroutine, preventing the response from being flushed.Expected Behavior
Same as
vault proxy— after detecting an invalid token, the agent should trigger re-authentication and retry with a fresh token.Additional Impact
authInProgressvariable is also not wired (agent.goL552), so the handler always readsfalseand always attempts the channel send, even during actual re-authenticationvault proxyis not always feasible — the Vault Agent Injector for Kubernetes only supports injectingvault agent, notvault proxy(see vault-k8s #495)Affected Versions
v1.17.0 through v1.21.4, and current
mainbranch (v2.0.2).Possible Fix
Add the two missing assignments in
command/agent.go, afterahis created (around line 600), matching whatcommand/proxy.goalready does:Thank you for your time, and for the great work on the self-healing feature.