nebula-mesh: Certificate Revocation Never Enforced at Mesh, CVE-2026-61699 (Critical) -DC-Jul2026-991

Listen to this Post

Nebula-mesh is a management layer for Slack’s Nebula overlay networking tool. It provides a web UI and API to manage hosts, CAs, and certificates across a mesh network.
A critical vulnerability exists in how nebula-mesh handles certificate revocation. When an operator blocks a host via the UI or API, nebula-mesh adds the host’s certificate fingerprint to a per-CA blocklist. The server side is fully implemented: it computes this blocklist via `GetBlocklistForCA` and returns it in the agent-updates response, setting `has_updates=true` when the list is non-empty.
Slack’s Nebula enforces certificate revocation only through the `pki.blocklist` list in config.yml—there is no CRL or OCSP support. The project’s own code states: “Revocation via the blocklist remains the immediate security control”.
However, the agent side of nebula-mesh was never implemented to apply this blocklist. Specifically:
– The agent decodes the `blocklist` JSON field into `UpdatesResponse.Blocklist` but then discards it. The `poll()` function applies CertificatePEM, CACertPEM, and ConfigYAML, but never references updates.Blocklist.
– The config generator has no field to emit pki.blocklist. The `pkiSection` only contains ca, cert, and key, and `GeneratorInput` carries no blocklist. Therefore, even the server-rendered `config.yml` shipped via `ConfigYAML` cannot carry the blocklist.
As a result, a blocked, offboarded, or compromised host’s certificate is never rejected by its peers. Handshakes continue to succeed for the full remaining certificate lifetime—up to 30 days for agent hosts (DefaultAgentCertDuration) and 365 days for mobile hosts (DefaultMobileCertDuration). Blocking a host in the UI/API has no effect on the data plane.
The vulnerability is distinct from CVE-2026-53602 (GHSA-339v), which concerns a blocked host getting a new certificate re-issued. This bug is that the existing certificate is never rejected at peers—the distribution and enforcement layer is broken.

DailyCVE Form

Platform: nebula-mesh
Version: <0.3.7
Vulnerability: Revocation never enforced
Severity: Critical
date: 2026-07-14

Prediction: Patch by 2026-08-15

What Undercode Say: Analytics

Server-side (intact):

– `internal/store/sqlite.go:2034` (GetBlocklistForCA)
– `internal/api/updates.go:182-191` (resp.Blocklist)
– `internal/api/updates.go:277` (has_updates set on blocklist change)

Agent-side (broken):

– `internal/agent/poller.go:33` (decodes Blocklist)
– `internal/agent/poller.go:300-339` (poll() applies cert/CA/config, never the blocklist)

Config generator (cannot emit):

– `internal/configgen/marshal.go:42-46` (pkiSection{CA,Cert,Key})
– `internal/configgen/generator.go:23-52` (GeneratorInput has no blocklist)
– `internal/api/enroll.go:255-330` (renderHostConfig, source of shipped ConfigYAML)

Dead helper:

– `internal/pki/blocklist.go` (Blocklist type) is never used in non-test code

Proof of Concept (benign):

$ go test ./internal/configgen/ -run TestPoC_NMESH001 -v
=== RUN TestPoC_NMESH001_GeneratedConfigOmitsBlocklist
CONFIRMED: generated config has a pki section but no blocklist key
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/host.crt
key: /etc/nebula/host.key
...
PASS

Exploit

Hop-by-hop attack path:

  1. Operator clicks “Block” on host B (or B is compromised/offboarded)

2. B’s fingerprint enters the per-CA `blocklist` table

  1. Every other host A under the same CA polls `GET /api/v1/agent/updates`

4. Server returns `blocklist: [, …]` and `has_updates=true`

5. A’s agent decodes `Blocklist` then discards it

6. `configgen.Generate` emits `pki: {ca,cert,key}` with no `blocklist` key
7. A’s Nebula daemon has an empty blocklist and accepts handshakes from B

8. B keeps full mesh access

Attacker scenario: An attacker who exfiltrates `host.key` + `host.crt` can run stock `slackhq/nebula` directly, ignore the agent’s 403/410 poll responses, and stay connected after the operator revokes the host.

Protection

Immediate mitigation:

  • Upgrade to nebula-mesh v0.3.7 or higher
  • Manually add the blocklist to every peer’s config.yml:
    pki:
    ca: /etc/nebula/ca.crt
    cert: /etc/nebula/host.crt
    key: /etc/nebula/host.key
    blocklist:</li>
    <li><fingerprint_of_blocked_host>
    
  • Restart or SIGHUP the Nebula daemon on every peer after updating the config

Permanent remediation (code fix):

  • Add `Blocklist []safeString` to `pkiSection` (with yaml:"blocklist,omitempty") and `GeneratorInput`
    – Consider adding `pki.disconnect_invalid: true`
    – Have the agent apply `updates.Blocklist` by re-rendering/rewriting `config.yml` + SIGHUP (same path as ConfigYAML)
  • Fold the blocklist into the server-rendered `ConfigYAML` so it flows through the existing write path
  • Add a regression test asserting a non-empty server blocklist yields a `pki.blocklist` entry in the agent’s written `config.yml`

Impact

  • Confidentiality: An attacker with a valid cert can access all internal services on the mesh
  • Integrity: Blocked/offboarded hosts can continue to participate in the mesh
  • Availability: Revocation—the only in-band isolation mechanism—is completely ineffective
  • Deception: Operator-visible state (UI shows blocked, audit log records it) is misleading
  • Duration: Exposure persists for up to 30 days (agent) or 365 days (mobile)

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top