GHSA-9PG3-25FQ-P6CC

Vulnerability from github – Published: 2026-06-10 22:13 – Updated: 2026-06-10 22:13
VLAI
Summary
nebula-mesh: Newly-minted operator API key exposed in redirect URL (Referer, history, proxy logs)
Details

internal/web/operators.go:251 — after handleOperatorCreateAPIKey mints a fresh 32-byte bearer token, the redirect points the operator's browser at:

/ui/operators/<id>?new_key=<raw-token>&key_name=<name>

The raw API key ends up: - in the browser's URL history - in the Referer header on every cross-origin asset the detail page loads (any third-party SVG/CSS/JS resource the layout pulls in) - in any reverse-proxy or load-balancer access log on the path (nginx default combined log captures the query string) - in any structured log sink the operator's local browser-history backup tool ships out

Authorization: Bearer <token> headers go through the same hops without these problems because access logs typically don't capture request headers and the browser doesn't replay headers cross-origin.

Same handler also appends name (r.FormValue("name")) to the query string without url.QueryEscape, so an & in the operator-supplied key name corrupts query parsing and a \r\n in older proxies could split response headers.

Affected

All released versions up to v0.3.1.

Reproducer

As admin, create an API key via /ui/operators/<id>/api-keys (form POST). The 303 Location header carries the raw token in the query string. Open browser DevTools → Network → response headers; or check the reverse-proxy access log; or check the operator-detail page's Referer-emitting fetches.

Suggested fix

Stash the raw key in a one-shot server-side flash storage (e.g., a row in operator_sessions keyed by session token, with a one_shot_token column and consumed_at) or in a short-lived signed cookie. Render the key once inline on the detail page after the redirect, and clear the storage on render. Pattern mirrors the recovery-codes display in the TOTP flow.

If the flash-storage refactor is too invasive, the minimal fix is to render the key inline via a POST200 OK with HTML (no redirect), losing the post-redirect-get idiom but eliminating the URL exposure.

Also fix name query encoding with url.QueryEscape regardless of which fix shape lands.

CVSS estimate

AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N — 5.5 (medium). AV:L because realistic exploit requires log-read access on shared infrastructure (proxy, CDN, browser-history backup) the operator's session touches.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.3.1"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/juev/nebula-mesh"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.3.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47768"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-116",
      "CWE-532",
      "CWE-598"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-10T22:13:45Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "`internal/web/operators.go:251` \u2014 after `handleOperatorCreateAPIKey` mints a fresh 32-byte bearer token, the redirect points the operator\u0027s browser at:\n\n    /ui/operators/\u003cid\u003e?new_key=\u003craw-token\u003e\u0026key_name=\u003cname\u003e\n\nThe raw API key ends up:\n- in the browser\u0027s URL history\n- in the `Referer` header on every cross-origin asset the detail page loads (any third-party SVG/CSS/JS resource the layout pulls in)\n- in any reverse-proxy or load-balancer access log on the path (nginx default `combined` log captures the query string)\n- in any structured log sink the operator\u0027s local browser-history backup tool ships out\n\n`Authorization: Bearer \u003ctoken\u003e` headers go through the same hops without these problems because access logs typically don\u0027t capture request headers and the browser doesn\u0027t replay headers cross-origin.\n\nSame handler also appends `name` (`r.FormValue(\"name\")`) to the query string without `url.QueryEscape`, so an `\u0026` in the operator-supplied key name corrupts query parsing and a `\\r\\n` in older proxies could split response headers.\n\n## Affected\nAll released versions up to v0.3.1.\n\n## Reproducer\nAs admin, create an API key via `/ui/operators/\u003cid\u003e/api-keys` (form POST). The 303 Location header carries the raw token in the query string. Open browser DevTools \u2192 Network \u2192 response headers; or check the reverse-proxy access log; or check the operator-detail page\u0027s `Referer`-emitting fetches.\n\n## Suggested fix\nStash the raw key in a one-shot server-side flash storage (e.g., a row in `operator_sessions` keyed by session token, with a `one_shot_token` column and `consumed_at`) or in a short-lived signed cookie. Render the key once inline on the detail page after the redirect, and clear the storage on render. Pattern mirrors the recovery-codes display in the TOTP flow.\n\nIf the flash-storage refactor is too invasive, the minimal fix is to render the key inline via a `POST` \u2192 `200 OK with HTML` (no redirect), losing the post-redirect-get idiom but eliminating the URL exposure.\n\nAlso fix `name` query encoding with `url.QueryEscape` regardless of which fix shape lands.\n\n## CVSS estimate\nAV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N \u2014 5.5 (medium). AV:L because realistic exploit requires log-read access on shared infrastructure (proxy, CDN, browser-history backup) the operator\u0027s session touches.",
  "id": "GHSA-9pg3-25fq-p6cc",
  "modified": "2026-06-10T22:13:45Z",
  "published": "2026-06-10T22:13:45Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/juev/nebula-mesh/security/advisories/GHSA-9pg3-25fq-p6cc"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/juev/nebula-mesh"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "nebula-mesh: Newly-minted operator API key exposed in redirect URL (Referer, history, proxy logs)"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

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.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…