OpenBao's Kerberos Auth Method Accumulates Unaccessible Tokens
Description
Impact
In OpenBao's Kerberos auth method on the GET handler, or when an Authorization: Negotiate header is supplied, the response is includes a logical.Auth object in addition to an error message. This results in tokens being created with only the default policy, default TTL, and no entity information, which are hidden by the returned error message. No access to these tokens by the caller occurs and the authentication token is not ever made accessible outside of sys/raw. At most this could cause storage usage.
Patches
This is fixed in OpenBao v2.5.4.
Workarounds
Users may set a rate limit quota to limit the creation of these paths. As the path is unauthenticated, it isn't possible to deny access to it.
Reporter
This was discovered by an anonymous reporter.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In OpenBao ≤2.5.3, the Kerberos auth method's GET handler returns an empty `logical.Auth` object with an error, causing unaccessible default-token creation and storage bloat.
Vulnerability
In OpenBao's Kerberos auth method, the GET handler (or any request with an Authorization: Negotiate header) returns a logical.Response containing an empty logical.Auth{} object at the same time as an error message [1][3]. This code path is reachable by any unauthenticated caller without special configuration. Affected versions are OpenBao up to and including v2.5.3 [3]. The issue was discovered by an anonymous reporter [3].
Exploitation
An attacker only needs network access to an OpenBao instance with the Kerberos auth method enabled; no authentication or user interaction is required [3]. The attacker sends a GET request or supplies an Authorization: Negotiate header to the Kerberos login endpoint. The server processes the request and, due to the bug, returns both an error and a logical.Auth object. The response error hides the fact that a token was created behind the scenes [1][4]. The token is never provided to the caller and can only be discovered via sys/raw [3].
Impact
Each such request creates an orphaned token with only the default policy, default TTL, and no entity information [3]. The caller never receives or gains control of the token, but the token consumes storage space in the backend [3]. While the impact is limited to storage usage bloat, repeated exploitation could lead to excessive storage consumption and potential denial of service through exhaustion of storage capacity [3][4].
Mitigation
This vulnerability is fixed in OpenBao v2.5.4, released on 2026-05-20 [2][3]. Users should upgrade to v2.5.4 or later. For users who cannot upgrade immediately, setting a rate limit quota on the Kerberos auth path can limit the rate of token creation; however, because the path is unauthenticated, it is not possible to deny access entirely [3].
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
10d82e0a5a3b6Prevent errors from creating orphaned tokens (#3150)
5 files changed · +123 −2
builtin/credential/kerberos/path_login.go+0 −1 modified@@ -66,7 +66,6 @@ func parseKeytab(b64EncodedKt string) (*keytab.Keytab, error) { func (b *backend) pathLoginGet(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { return &logical.Response{ - Auth: &logical.Auth{}, Headers: map[string][]string{ "www-authenticate": {"Negotiate"}, },
changelog/3150.txt+6 −0 added@@ -0,0 +1,6 @@ +```release-note:security +core: Prevent hidden default token issuance from auth plugin endpoints returning both a `logical.Auth{}` response object and an error. GHSA-7j6w-vvw2-5f9c / CVE-2026-46405. +``` +```release-note:bug +auth/kerberos: Do not return `logical.Auth{}` response during initial negotiation at the same time as an error. +```
tools/semgrep/ci/non-nil-err-auth-response.yml+59 −0 added@@ -0,0 +1,59 @@ +# Copyright (c) 2026 OpenBao a Series of LF Projects, LLC +# SPDX-License-Identifier: MPL-2.0 + +rules: + - id: non-nil-err-auth-response + patterns: + - pattern-either: + - pattern: | + return &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + }, err + - pattern: | + return &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + }, logical.CodedError(...) + - pattern: | + return &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + }, fmt.Errorf(...) + - pattern: | + return &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + }, errors.New(...) + - pattern: | + $FOO = &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + } + ... + return $FOO, err + - pattern: | + $FOO = &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + } + ... + return $FOO, logical.CodedError(...) + - pattern: | + $FOO = &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + } + ... + return $FOO, fmt.Errorf(...) + - pattern: | + $FOO = &logical.Response{ + Auth: &logical.Auth{ ... }, + ... + } + ... + return $FOO, errors.New(...) + message: a non-nil error should not include an auth response + languages: + - go + severity: ERROR
vault/request_handling.go+9 −1 modified@@ -1389,7 +1389,11 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp } // Only the token store is allowed to return an auth block, for any - // other request this is an internal error. + // other request this is an internal error. When the request fails, + // do not generate a token even if the backend returned an auth block. + if resp != nil && resp.Auth != nil && routeErr != nil { + resp.Auth = nil + } if resp != nil && resp.Auth != nil { if !strings.HasPrefix(req.Path, "auth/token/") { c.logger.Error("unexpected auth response for non-token backend", "request_path", req.Path) @@ -1672,6 +1676,10 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re } // If the response generated an authentication, then generate the token + // only if it did not also err as the err would shadow the token. + if resp != nil && resp.Auth != nil && routeErr != nil { + resp.Auth = nil + } if resp != nil && resp.Auth != nil && req.Path != "sys/mfa/validate" { // When the request path is part of a logical backend (and not a // credential backend), reject the token creation.
vault/request_handling_test.go+49 −0 modified@@ -5,6 +5,7 @@ package vault import ( "context" + "errors" "fmt" "strings" "testing" @@ -828,3 +829,51 @@ func TestRequestHandling_DisallowLogicalTokenCreation(t *testing.T) { } require.Error(t, err, ErrInternalError) } + +func TestRequestHandling_DisallowAuthErrorTokenCreation(t *testing.T) { + t.Parallel() + + core, _, root := TestCoreUnsealed(t) + + if err := core.loadMounts(namespace.RootContext(t.Context()), false); err != nil { + t.Fatalf("err: %v", err) + } + + core.credentialBackends["test"] = func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { + b := &backendTest.Noop{ + Login: []string{"login"}, + BackendType: logical.TypeCredential, + RequestHandler: func(ctx context.Context, req *logical.Request) (*logical.Response, error) { + return &logical.Response{ + Auth: &logical.Auth{}, + }, errors.New("erring for test") + }, + } + if err := b.Setup(ctx, conf); err != nil { + return nil, err + } + return b, nil + } + + req := &logical.Request{ + Path: "sys/auth/test", + ClientToken: root, + Operation: logical.UpdateOperation, + Data: map[string]interface{}{ + "type": "test", + }, + } + resp, err := core.HandleRequest(namespace.RootContext(t.Context()), req) + require.NoError(t, err) + require.Nil(t, resp) + + req = &logical.Request{ + Path: "auth/test/login", + Operation: logical.ReadOperation, + } + resp, err = core.HandleRequest(namespace.RootContext(t.Context()), req) + if resp != nil { + require.Nil(t, resp.Auth) + } + require.Error(t, err, ErrInternalError) +}
Vulnerability mechanics
Root cause
"The Kerberos auth method returns both a `logical.Auth{}` object and a non-nil error, causing the core framework to create an orphaned token that is hidden from the caller by the error response."
Attack vector
An unauthenticated attacker sends a GET request to the Kerberos auth endpoint, or supplies an `Authorization: Negotiate` header, triggering the initial negotiation path. The handler returns both a `logical.Auth{}` object (which triggers token creation) and an error message. The error is returned to the caller, hiding the fact that a token was created with only the default policy, default TTL, and no entity information [ref_id=1]. The attacker never receives the token itself, so the impact is limited to storage consumption from orphaned tokens [ref_id=1].
Affected code
The Kerberos auth method's `pathLoginGet` function in `builtin/credential/kerberos/path_login.go` returned a `logical.Response` containing an empty `Auth: &logical.Auth{}` alongside an error [patch_id=2973534]. The core request handling in `vault/request_handling.go` did not strip the `Auth` block when the backend also returned a non-nil error, allowing token creation despite the error [patch_id=2973534].
What the fix does
The patch makes two changes. First, in `builtin/credential/kerberos/path_login.go`, the empty `Auth: &logical.Auth{}` is removed from the response returned during initial negotiation, preventing the auth method from ever returning an auth block with an error [patch_id=2973534]. Second, in `vault/request_handling.go`, both `handleRequest` and `handleLoginRequest` now check if `resp.Auth` is non-nil while `routeErr` is also non-nil, and if so, set `resp.Auth = nil` before token creation proceeds [patch_id=2973534]. This ensures that even if another backend makes the same mistake, the core framework will not create a token from a failed request. A new Semgrep rule (`non-nil-err-auth-response`) was also added to catch this pattern at code review time [patch_id=2973534].
Preconditions
- authNo authentication required — the Kerberos auth endpoint is unauthenticated
- networkAttacker must be able to reach the OpenBao HTTP API
- configThe Kerberos auth method must be enabled on the OpenBao instance
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5News mentions
0No linked articles in our index yet.