nebula-mesh CVE-2026-47725
HIGHLifecycle Timeline
2DescriptionCVE.org
Every /ui/* POST / PUT / PATCH / DELETE route processes the request as soon as the session cookie validates. SameSite=Lax on the session cookie prevents most cross-site form submits but does not protect:
- top-level form-submit navigations from third-party pages (some browsers still send Lax cookies on top-level POSTs)
- same-registrable-domain attackers (sibling-subdomain XSS, subdomain takeover)
- the
GET /ui/logoutroute, which a third-party<img src=".../ui/logout">can force-trigger
The admin UI signs CA certificates, mints API keys, rotates / retires / deletes CAs, disables operators, and changes server settings. CSRF here is a real privilege escalation, not just annoyance.
Affected
All released versions up to v0.3.2.
Suggested fix
Double-submit cookie: a 32-byte crypto/rand token in a non-HttpOnly _csrf cookie, echoed in either X-CSRF-Token (htmx) or a _csrf form field (HTML forms). Compared in constant time. Rotated on every privilege transition (Login, OIDC StartAuthenticatedSession, CompleteTwoFactor, Logout) so pre-auth fixation cannot survive promotion. Rejections audit-logged as ui.csrf.rejected with reason; response body stays opaque.
/ui/logout becomes POST so it is no longer reachable via <img> tags.
Fix coordinates with the Secure-cookie advisory disclosed concurrently - the _csrf cookie inherits the same Secure-attribute derivation.
Reproducer
With an authenticated operator session in browser tab A, open the following minimal HTML in any other tab:
<form action="https://nebula.example.com/ui/cas/{ca-id}/delete" method="POST">
<button>Click for free puppy</button>
</form>Click. The CA is deleted - the server processes the POST because the session cookie is automatically attached and there is no other check. The same trick works for force-rotate, retire, mint API keys, disable operators, etc.
Alternative force-logout: <img src="https://nebula.example.com/ui/logout"> placed on an attacker's page logs out any visiting authenticated operator. No interaction required.
Notes
- Multipart and JSON endpoints don't exist in the current UI surface. Future additions must rely on the header path because
r.PostFormValueonly readsapplication/x-www-form-urlencodedbodies. The middleware's package comment documents this. - The patch assumes nebula-mgmt is the sole authority on its registrable domain. A compromised sibling subdomain can still set parent-domain cookies and forge matches; SameSite=Lax does not prevent that. Documented in the patch.
AnalysisAI
Cross-site request forgery in nebula-mesh's admin web UI (versions <= 0.3.2) lets a remote attacker trigger privileged operator actions - CA signing, API key minting, operator disablement, server-setting changes, and forced logout - when a logged-in operator visits an attacker-controlled page. SameSite=Lax on the session cookie does not block top-level cross-site form POSTs, sibling-subdomain attackers, or the GET /ui/logout route, so the impact is privilege escalation rather than nuisance. No public exploit identified at time of analysis beyond the working reproducer in the advisory itself.
Technical ContextAI
nebula-mesh is a Go-based management plane for the Nebula overlay mesh network, exposing an htmx-driven /ui/* admin surface for CA lifecycle, API key issuance, operator management, and server configuration. The vulnerability is a classic CWE-352-style omission misclassified here as CWE-269 (Improper Privilege Management): every state-changing /ui/* route authenticates the request solely via the session cookie, with no token, custom header, or origin/referer check. The application relies on r.PostFormValue, which only parses application/x-www-form-urlencoded bodies, so a simple cross-site HTML <form> submit is sufficient - and because /ui/logout is wired as GET, even an <img> tag from a third-party page triggers it. The fix introduces a double-submit cookie pattern (32-byte crypto/rand token in a non-HttpOnly _csrf cookie, echoed in X-CSRF-Token or a _csrf form field, constant-time compared, rotated on every privilege transition).
RemediationAI
Vendor-released patch: upgrade github.com/juev/nebula-mesh to v0.3.3 or later, which introduces a double-submit CSRF cookie validated on every /ui/* mutating route and converts /ui/logout from GET to POST so it can no longer be force-triggered via <img> tags; see https://github.com/juev/nebula-mesh/security/advisories/GHSA-273q-qgh5-wrj6 for full details. If immediate upgrade is not possible, the most effective compensating controls are to deploy nebula-mesh on a dedicated registrable domain (not a shared parent domain, since the patch itself warns SameSite=Lax cannot defeat sibling-subdomain forgery), restrict the /ui/* surface to a management VLAN or VPN so operator browsers cannot reach it from general-purpose web sessions, and instruct operators to use a separate browser profile or container exclusively for admin work - the trade-off being operational friction and the loss of convenience features like single-sign-on across tabs. Adding a reverse-proxy rule that rejects /ui/* requests whose Origin or Referer header does not match the management host is another stopgap, but it will break legitimate htmx flows if the proxy is misconfigured and offers no protection against same-site attackers.
Same weakness CWE-269 – Improper Privilege Management
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-273q-qgh5-wrj6