Skip to main content

nebula-mesh CVE-2026-48025

MEDIUM
Improper Clearing of Heap Memory Before Release ('Heap Inspection') (CWE-244)
2026-06-10 https://github.com/juev/nebula-mesh GHSA-8h84-fhqq-q58v
Share

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 10, 2026 - 19:16 vuln.today
Analysis Generated
Jun 10, 2026 - 19:16 vuln.today

DescriptionCVE.org

internal/pki/resolver.go:36-64 constructs a CAManager with the plaintext ed25519.PrivateKey after unwrapping via the master key; internal/pki/ca.go:13-16 stores it. Callers at internal/api/enroll.go:116, internal/api/updates.go:297, and internal/api/mobile_bundle.go:40 use the manager for one Sign() and drop the reference on function return - but the underlying slice contents are not wiped before release.

The keystore package's contract (internal/keystore/keystore.go doc: *"Callers MUST zeroise the returned plaintext DEK as soon as it is no longer needed"*) is not met by the CAManager consumer. Decrypted CA private keys persist in process heap until Go's GC scavenges the underlying slice - minutes to hours under load, indefinitely on idle servers.

Affected

All released versions up to v0.3.6.

Threat model

Memory-read access: core dump, ptrace, kernel swap to disk, container/VM snapshot, OOM-debug bundle, side-channel via shared cache lines. Not a remote-network vulnerability, but defeats the master-key + envelope-encryption design's promise of "private key never lingers".

Suggested fix

Add a Wipe() method on CAManager:

go
// internal/pki/ca.go
func (m *CAManager) Wipe() {
    if m == nil {
        return
    }
    keystore.Zeroize(m.caKey)
}

At each call site (enroll.go:116, updates.go:297, mobile_bundle.go:40, and any new caller), defer caMgr.Wipe() immediately after the Resolve() call. Pattern mirrors the existing defer keystore.Zeroize(dek) discipline in the keystore package.

Optional follow-up: wrap m.Sign() to zeroize after each call, removing the contract on callers - but the defer pattern is sufficient as a minimum.

AnalysisAI

Decrypted CA private keys in nebula-mesh linger in Go's process heap after signing operations complete, violating the keystore package's explicit zeroise contract. All versions through v0.3.6 are affected across three call sites - enroll.go:116, updates.go:297, and mobile_bundle.go:40 - each of which constructs a CAManager with a plaintext ed25519.PrivateKey and drops the reference without wiping the underlying slice. An attacker with local memory-read access can extract the plaintext CA private key from process heap, defeating the master-key envelope-encryption design's core security guarantee. No public exploit has been identified at time of analysis and the vulnerability is not listed in CISA KEV.

Technical ContextAI

The affected package is pkg:go/github.com_juev_nebula-mesh, a Go-based mesh networking PKI system. The keystore package wraps CA private keys under a master key using envelope encryption; resolver.go:36-64 unwraps the ed25519.PrivateKey via the master key and passes the plaintext bytes to CAManager, which stores them in ca.go:13-16. The keystore package explicitly documents - 'Callers MUST zeroise the returned plaintext DEK as soon as it is no longer needed' - but CAManager never calls zeroise before releasing its reference. In Go, dropping a reference does not zero memory; the GC may reclaim the underlying slice minutes to hours later under load, or not at all on idle servers. The root cause class is CWE-244 (Improper Clearing of Heap Memory Before Release), a memory-hygiene failure in cryptographic key handling. The fix in v0.3.7 introduces a loadCAOrZeroize() wrapper that zeroizes keyBytes on error paths, and a CAManager.Wipe() method used via defer at each call site, mirroring the existing defer keystore.Zeroize(dek) discipline elsewhere in the codebase.

RemediationAI

Upgrade to nebula-mesh v0.3.7, which introduces the CAManager.Wipe() method and the loadCAOrZeroize() helper; the fix is confirmed by commit bca1d5914fbaf3517d3b86145a802c00de4a8122 and the v0.3.7 release tag at https://github.com/forgekeep/nebula-mesh/releases/tag/v0.3.7. If immediate upgrade is not possible, the compensating control is to restrict memory-read access to the nebula-mesh server process: disable ptrace on the host (set /proc/sys/kernel/yama/ptrace_scope to 2 or 3), disable core dumps for the process (ulimit -c 0 or systemd LimitCORE=0), ensure container snapshots and VM memory dumps are access-controlled to trusted operators only, and audit OOM debug tooling to prevent capture of the process heap. These controls reduce the window of exposure but do not eliminate the underlying key residency in heap memory; only the v0.3.7 patch resolves the root cause.

Share

CVE-2026-48025 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy