Every CVESearch/Get API key

GHSA-v2jf-442r-6mjh

nebula-mesh: Signed-poll nonce LRU is in-memory and bounded; replay survives restart + eviction

2.7 LowFix available

GHSA-v2jf-442r-6mjh is a low vulnerability (CVSS 2.7) in github.com/juev/nebula-mesh, published June 26, 2026. No source lists public exploit code. Fixed in github.com/juev/nebula-mesh 0.3.4.

Severity
2.7 LowCVSS 4.0, GitHub Advisories
Exploit chance
UnscoredNo EPSS score yet
Exploitation
None knownNot on CISA’s or ENISA’s lists

Description

internal/api/pop/nonce.go:25,40,86 + internal/api/server.go:38 — the signed-poll nonce cache is an in-process LRU sized at 65,536 entries. internal/api/updates.go:31 sets pollClockSkew = 5 * time.Minute as the replay window.

Affected

All released versions through v0.3.0 that have shipped the ADR 0004 signed-poll path. (If this is gated behind a feature flag, on a side branch, or not yet on a release tag, please flag — this advisory may not apply to the released artifact yet.)

Threat model

A captured signed-poll request can be replayed:

  1. After any process restart — the in-memory LRU is wiped, so the original nonce becomes "unseen" again. Replay succeeds if the original timestamp is still within the 5-minute skew.
  2. After forced eviction — an attacker with control of any single host can flood >65,536 nonces under their own host_id, driving the global LRU to evict the victim's recorded nonce. Replay then succeeds.

Impact is bounded: a replayed poll fetches the /api/v1/agent/updates body. That body can include a freshly-minted enrollment token if a rekey is pending (updates.go:249-260) — at which point the attacker holds a single-use token they can redeem under their own keypair.

Suggested fix

Two options, either acceptable:

  1. Persist nonces in SQLite keyed by (host_id, nonce) with ON CONFLICT DO NOTHING, retained for the timestamp-skew window. Adds one transactional INSERT per poll; bounded by the skew window (~5 min worth of rows server-wide).
  2. Per-host cap on the LRU instead of a global 65k cap, so one host cannot evict another's records. Combined with shorter skew (≤30s) to bound the post-restart replay window.

Option 1 is more robust; option 2 is lower-implementation-effort.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
Low
Availability
None

Affected packages

Affected packages
PackageAffectedFixed
github.com/juev/nebula-mesh
Go
through 0.3.3
0.3.4
github.com/juev/nebula-mesh
Go
before 0.3.4
0.3.4

What each source reports

GitHub Advisories Score used2.7

nebula-mesh: Signed-poll nonce LRU is in-memory and bounded; replay survives restart + eviction

internal/api/pop/nonce.go:25,40,86 + internal/api/server.go:38 — the signed-poll nonce cache is an in-process LRU sized at 65,536 entries. internal/api/updates.go:31 sets pollClockSkew = 5 * time.Minute as the replay window.

Affected

All released versions through v0.3.0 that have shipped the ADR 0004 signed-poll path. (If this is gated behind a feature flag, on a side branch, or not yet on a release tag, please flag — this advisory may not apply to the released artifact yet.)

Threat model

A captured signed-poll request can be replayed:

  1. After any process restart — the in-memory LRU is wiped, so the original nonce becomes "unseen" again. Replay succeeds if the original timestamp is still within the 5-minute skew.
  2. After forced eviction — an attacker with control of any single host can flood >65,536 nonces under their own host_id, driving the global LRU to evict the victim's recorded nonce. Replay then succeeds.

Impact is bounded: a replayed poll fetches the /api/v1/agent/updates body. That body can include a freshly-minted enrollment token if a rekey is pending (updates.go:249-260) — at which point the attacker holds a single-use token they can redeem under their own keypair.

Suggested fix

Two options, either acceptable:

  1. Persist nonces in SQLite keyed by (host_id, nonce) with ON CONFLICT DO NOTHING, retained for the timestamp-skew window. Adds one transactional INSERT per poll; bounded by the skew window (~5 min worth of rows server-wide).
  2. Per-host cap on the LRU instead of a global 65k cap, so one host cannot evict another's records. Combined with shorter skew (≤30s) to bound the post-restart replay window.

Option 1 is more robust; option 2 is lower-implementation-effort.

Record
GHSA-v2jf-442r-6mjh
CVSS 4.0
2.7 LowCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U
Weakness
CWE-294
Updated
2026-11-02
OSV2.7

nebula-mesh: Signed-poll nonce LRU is in-memory and bounded; replay survives restart + eviction

internal/api/pop/nonce.go:25,40,86 + internal/api/server.go:38 — the signed-poll nonce cache is an in-process LRU sized at 65,536 entries. internal/api/updates.go:31 sets pollClockSkew = 5 * time.Minute as the replay window.

Affected

All released versions through v0.3.0 that have shipped the ADR 0004 signed-poll path. (If this is gated behind a feature flag, on a side branch, or not yet on a release tag, please flag — this advisory may not apply to the released artifact yet.)

Threat model

A captured signed-poll request can be replayed:

  1. After any process restart — the in-memory LRU is wiped, so the original nonce becomes "unseen" again. Replay succeeds if the original timestamp is still within the 5-minute skew.
  2. After forced eviction — an attacker with control of any single host can flood >65,536 nonces under their own host_id, driving the global LRU to evict the victim's recorded nonce. Replay then succeeds.

Impact is bounded: a replayed poll fetches the /api/v1/agent/updates body. That body can include a freshly-minted enrollment token if a rekey is pending (updates.go:249-260) — at which point the attacker holds a single-use token they can redeem under their own keypair.

Suggested fix

Two options, either acceptable:

  1. Persist nonces in SQLite keyed by (host_id, nonce) with ON CONFLICT DO NOTHING, retained for the timestamp-skew window. Adds one transactional INSERT per poll; bounded by the skew window (~5 min worth of rows server-wide).
  2. Per-host cap on the LRU instead of a global 65k cap, so one host cannot evict another's records. Combined with shorter skew (≤30s) to bound the post-restart replay window.

Option 1 is more robust; option 2 is lower-implementation-effort.

Record
GHSA-v2jf-442r-6mjh
CVSS 4.0
2.7 LowCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U
Weakness
CWE-294
Updated
2026-11-02
OSVGO-2026-5815No score

nebula-mesh: Signed-poll nonce LRU is in-memory and bounded; replay survives restart + eviction in github.com/juev/nebula-mesh

nebula-mesh: Signed-poll nonce LRU is in-memory and bounded; replay survives restart + eviction in github.com/juev/nebula-mesh

Record
GO-2026-5815
Updated
2026-11-02

History

History
RecordedChangedSources
first indexedGitHub Advisories, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

References

MoveEnter Open