GHSA-273Q-QGH5-WRJ6
Vulnerability from github – Published: 2026-06-08 23:09 – Updated: 2026-06-08 23:09Every /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.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.3.2"
},
"package": {
"ecosystem": "Go",
"name": "github.com/juev/nebula-mesh"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.3.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47725"
],
"database_specific": {
"cwe_ids": [
"CWE-269",
"CWE-352"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-08T23:09:21Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "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:\n\n- top-level form-submit navigations from third-party pages (some browsers still send Lax cookies on top-level POSTs)\n- same-registrable-domain attackers (sibling-subdomain XSS, subdomain takeover)\n- the `GET /ui/logout` route, which a third-party `\u003cimg src=\".../ui/logout\"\u003e` can force-trigger\n\nThe 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.\n\n## Affected\nAll released versions up to v0.3.2.\n\n## Suggested fix\nDouble-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.\n\n`/ui/logout` becomes POST so it is no longer reachable via `\u003cimg\u003e` tags.\n\nFix coordinates with the Secure-cookie advisory disclosed concurrently \u2014 the `_csrf` cookie inherits the same `Secure`-attribute derivation.\n\n## Reproducer\nWith an authenticated operator session in browser tab A, open the following minimal HTML in any other tab:\n\n```html\n\u003cform action=\"https://nebula.example.com/ui/cas/{ca-id}/delete\" method=\"POST\"\u003e\n \u003cbutton\u003eClick for free puppy\u003c/button\u003e\n\u003c/form\u003e\n```\n\nClick. The CA is deleted \u2014 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.\n\nAlternative force-logout: `\u003cimg src=\"https://nebula.example.com/ui/logout\"\u003e` placed on an attacker\u0027s page logs out any visiting authenticated operator. No interaction required.\n\n## Notes\n- Multipart and JSON endpoints don\u0027t exist in the current UI surface. Future additions must rely on the header path because `r.PostFormValue` only reads `application/x-www-form-urlencoded` bodies. The middleware\u0027s package comment documents this.\n- 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.",
"id": "GHSA-273q-qgh5-wrj6",
"modified": "2026-06-08T23:09:21Z",
"published": "2026-06-08T23:09:21Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/juev/nebula-mesh/security/advisories/GHSA-273q-qgh5-wrj6"
},
{
"type": "PACKAGE",
"url": "https://github.com/juev/nebula-mesh"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "nebula-mesh\u0027s web UI lacks CSRF tokens on /ui/* mutating endpoints"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.