CVE-2026-55512: nebula-mesh Unauthenticated OIDC Login Endpoint Allocates Vulnerability
MODERATECVE-2026-55512 is a MODERATE (CVSS 5.3) unauthenticated oidc login endpoint allocates vulnerability (CWE-400: Uncontrolled Resource Consumption) affecting nebula-mesh libraries in the Go ecosystem. The issue involves unauthenticated oidc login endpoint allocates unbounded in-memory state entries without rate limiting. Remediation is available by upgrading affected packages to version 0.5.0.
CVE-2026-55512 at a Glance
Security Impact
CVSS: 5.3
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L).
How to Fix CVE-2026-55512
To remediate this vulnerability, upgrade all affected nebula-mesh dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/forgekeep/nebula-mesh to 0.5.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/forgekeep/nebula-mesh
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-55512, inspect your project dependencies for nebula-mesh:
inspect dependencies for github.com/forgekeep/nebula-mesh
Analyze the terminal output to locate any version of nebula-mesh in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.5.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption, where the product does not properly control the allocation and maintenance of a limited resource. In nebula-mesh, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-55512 Affected nebula-mesh Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/forgekeep/nebula-mesh
|
Go |
≥ 0.2.0
< 0.5.0
|
0.5.0
|
References
Frequently Asked Questions
What is CVE-2026-55512?
Which nebula-mesh versions are affected?
What version fixes CVE-2026-55512?
Is github.com/forgekeep/nebula-mesh affected?
What is the CVSS score of CVE-2026-55512?
What CWE is associated with CVE-2026-55512?
How can I check Go dependencies for CVE-2026-55512?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-m3cx-mwpg-32jg",
"modified" : "2026-07-14T20:19:32Z",
"published" : "2026-07-14T20:19:32Z",
"aliases" : [ "CVE-2026-55512" ],
"summary" : "nebula-mesh: Unauthenticated OIDC login endpoint allocates unbounded in-memory state entries without rate limiting",
"details" : "### Summary\nWhen OIDC is enabled, `GET /ui/oidc/login` is reachable without authentication and is registered outside the Web UI rate-limited auth routes. Every request creates a fresh random OIDC state value and stores it in an in-memory map for `10m`. Expired states are swept lazily, but there is no rate limit or maximum live-state cap on the allocation path. An unauthenticated remote client can therefore grow `OIDC.states` for the full state TTL, bounded by request throughput rather than by configured auth rate limits.\n\n### Details\nThe OIDC login route is registered directly by `WithOIDC`:\n\n- `internal/web/web.go:153` registers `w.router.Get(\"/ui/oidc/login\", o.HandleLogin)`.\n- `internal/web/web.go:154` rate-limits only `GET /ui/oidc/callback` with `w.rateLimitMiddleware(\"auth\")`.\n\nThe normal `/ui/*` route group applies rate limiting to login/register form submissions, but this direct registration happens outside that group:\n\n- `internal/web/web.go:287` through `internal/web/web.go:292` show the rate-limited local login, TOTP, and register POST routes.\n\nThe OIDC login handler allocates persistent server-side state before redirecting to the configured identity provider:\n\n- `internal/web/oidc.go:105` defines `HandleLogin`.\n- `internal/web/oidc.go:106` creates a random state token.\n- `internal/web/oidc.go:112` calls `o.rememberState(state)`.\n- `internal/web/oidc.go:122` redirects to `o.oauth.AuthCodeURL(state)`.\n\nThe state storage has a TTL but no maximum size:\n\n- `internal/web/oidc.go:24` through `internal/web/oidc.go:26` define `oidcStateTTL = 10 * time.Minute`.\n- `internal/web/oidc.go:353` through `internal/web/oidc.go:358` sweep expired states and then add the new state to `o.states`.\n- `internal/web/oidc.go:360` through `internal/web/oidc.go:373` delete only expired states.\n\nBecause the route is unauthenticated and not rate-limited, a remote client can repeatedly request `/ui/oidc/login` and force live state entries to accumulate for ten minutes. OIDC must be enabled for exposure. No IdP callback, valid credentials, or user interaction is required to trigger the allocation.\n\nAffected version evidence: OIDC login support was introduced by commit `3f46685` (`feat(auth): add OIDC operator login (Keycloak/Authentik/Okta/...) (#24)`), and `git tag --contains 3f46685 --sort=version:refname` returns `v0.2.0` and every later release through `v0.3.8`. Pattern checks across all release tags showed the OIDC login route and state allocation are present in `v0.2.0` and in every `v0.3.x` release from `v0.3.0` to `v0.3.8`, and absent from `v0.1.x`. The current checkout at commit `d92dd9a60de291e2bc1caf73b4e9a99567b31ec0` (`git describe`: `v0.3.8-1-gd92dd9a`) remains affected.\n\n### PoC\nSafe local PoC run from a clean checkout at commit `d92dd9a60de291e2bc1caf73b4e9a99567b31ec0` on 2026-06-12. The PoC is a temporary Go test that uses `httptest` and an in-memory OIDC object; it does not start a real server, does not contact an IdP, and uses 1000 requests only to demonstrate linear state growth.\n\n1. Create a temporary test file `internal/web/security_audit_poc_test.go` in package `web`.\n2. Create a test Web UI with `newTestWeb(t)`.\n3. Install a deliberately tiny auth rate limiter: group `auth` with rate `0.001` and burst `2`.\n4. Attach an `OIDC` instance with an empty `states` map and an `oauth2.Config` whose authorization endpoint is `https://idp.example.test/auth`.\n5. Send 1000 unauthenticated `GET /ui/oidc/login` requests from the same `RemoteAddr` through `w.ServeHTTP`.\n6. Assert no request returns `429 Too Many Requests`, then inspect `o.stateCount()`.\n\nCommand run:\n\n```bash\ngo test ./internal/web -run 'TestSecurityAuditPOC' -count=1 -v\n```\n\nObserved vulnerable output from this environment:\n\n```text\n=== RUN TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState\nPOC_OIDC_STATE_GROWTH attempts=1000 live_states=1000 ttl=10m0s rate_limit_group=auth_burst_2\n--- PASS: TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState (0.10s)\n```\n\nThe meaningful control is that local login/register/TOTP POST routes and the OIDC callback are rate-limited: `internal/web/web.go:287` through `internal/web/web.go:292` and `internal/web/web.go:154`. The PoC specifically shows the OIDC login allocation route does not share that protection. After recording the output, the temporary test file was removed and `git status --short` returned clean. The PoC was re-run after drafting this report and produced the output shown above.\n\n### Impact\nIn deployments with OIDC enabled, an unauthenticated remote client can cause application-layer memory growth by repeatedly requesting `/ui/oidc/login`. Each request stores a new state entry for ten minutes, and the growth is not bounded by the configured auth rate limiter or by a maximum map size. The demonstrated impact is availability degradation risk through retained in-memory state growth. The PoC used 1000 local requests to avoid disruptive load while proving the source-to-sink behavior (`1000` requests resulted in `1000` live states).\n\nSuggested remediation: apply the existing `auth` rate limiter to `GET /ui/oidc/login`, add a maximum number of live OIDC states per client and/or globally, and fail closed when the cap is reached. Add a regression test that attaches a low-burst auth limiter, sends repeated `GET /ui/oidc/login` requests from the same client, and expects `429` or bounded live-state count after the configured burst.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/forgekeep/nebula-mesh"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0.2.0"
}, {
"fixed" : "0.5.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/forgekeep/nebula-mesh/security/advisories/GHSA-m3cx-mwpg-32jg"
}, {
"type" : "WEB",
"url" : "https://github.com/forgekeep/nebula-mesh/commit/bc387086cc0e4b9c1654468b7391af19cacfe367"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/forgekeep/nebula-mesh"
}, {
"type" : "WEB",
"url" : "https://github.com/forgekeep/nebula-mesh/releases/tag/v0.5.0"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-400" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-14T20:19:32Z",
"nvd_published_at" : null
}
}