GHSA-Q4VM-PQ3Q-8WGQ

Vulnerability from github – Published: 2026-07-14 20:17 – Updated: 2026-07-14 20:17
VLAI
Summary
nebula-mesh: Operator session tokens stored in plaintext in the database
Details

Impact

Operator session tokens are stored in plaintext in the operator_sessions table (the token column is the PRIMARY KEY). The session token is a 32-byte random hex value sent directly in a cookie and valid for 24 hours.

  • internal/models/operator.go:61 — OperatorSession.Token holds the plaintext token.
  • internal/store/sqlite_operators.go:590 — CreateOperatorSession inserts sess.Token verbatim.
  • internal/store/sqlite_operators.go:603,642,681,698 — lookups/updates/deletes use WHERE token = ? against the plaintext value.

Anyone who can read the database (backup, snapshot, file copy, or SQL-level disclosure) obtains every active session token and can hijack operator sessions directly, with no further authentication.

This is functionally identical to the plaintext enrollment-token issue fixed in GHSA-ghmh-jhmj-wcmf. API keys (OperatorAPIKey.KeyHash) and enrollment tokens (EnrollmentToken.TokenHash) already store only a SHA256 hash; session tokens were missed.

Patches

Store only a SHA256 hash of the session token, mirroring API keys and enrollment tokens: 1. Add a HashSessionToken helper (alongside the existing token-hash helpers). 2. Migration to add a token_hash column. 3. Update CreateOperatorSession, PromoteOperatorSession, and GetOperatorBySession to write/look up by hash. 4. Drop the plaintext token column in a follow-up migration.

Sessions are ephemeral (24h TTL), so all active sessions can be invalidated on deployment — no backward compatibility needed.

Workarounds

Restrict and encrypt database backups; rotate the operator database. These mitigate exposure but do not fix the underlying storage of plaintext tokens.

Resources

  • internal/models/operator.go:58-66
  • internal/store/sqlite_operators.go:577-698
  • Migration 005_operators.up.sql:27
  • Prior related advisory: GHSA-ghmh-jhmj-wcmf
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.3.7"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/forgekeep/nebula-mesh"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.3.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-53603"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-312",
      "CWE-522"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-14T20:17:04Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Impact\n\nOperator session tokens are stored in plaintext in the `operator_sessions` table (the `token` column is the PRIMARY KEY). The session token is a 32-byte random hex value sent directly in a cookie and valid for 24 hours.\n\n- `internal/models/operator.go:61` \u2014 `OperatorSession.Token` holds the plaintext token.\n- `internal/store/sqlite_operators.go:590` \u2014 `CreateOperatorSession` inserts `sess.Token` verbatim.\n- `internal/store/sqlite_operators.go:603,642,681,698` \u2014 lookups/updates/deletes use `WHERE token = ?` against the plaintext value.\n\nAnyone who can read the database (backup, snapshot, file copy, or SQL-level disclosure) obtains every active session token and can hijack operator sessions directly, with no further authentication.\n\nThis is functionally identical to the plaintext enrollment-token issue fixed in GHSA-ghmh-jhmj-wcmf. API keys (`OperatorAPIKey.KeyHash`) and enrollment tokens (`EnrollmentToken.TokenHash`) already store only a SHA256 hash; session tokens were missed.\n\n## Patches\n\nStore only a SHA256 hash of the session token, mirroring API keys and enrollment tokens:\n1. Add a `HashSessionToken` helper (alongside the existing token-hash helpers).\n2. Migration to add a `token_hash` column.\n3. Update `CreateOperatorSession`, `PromoteOperatorSession`, and `GetOperatorBySession` to write/look up by hash.\n4. Drop the plaintext `token` column in a follow-up migration.\n\nSessions are ephemeral (24h TTL), so all active sessions can be invalidated on deployment \u2014 no backward compatibility needed.\n\n## Workarounds\n\nRestrict and encrypt database backups; rotate the operator database. These mitigate exposure but do not fix the underlying storage of plaintext tokens.\n\n## Resources\n\n- `internal/models/operator.go:58-66`\n- `internal/store/sqlite_operators.go:577-698`\n- Migration `005_operators.up.sql:27`\n- Prior related advisory: GHSA-ghmh-jhmj-wcmf",
  "id": "GHSA-q4vm-pq3q-8wgq",
  "modified": "2026-07-14T20:17:04Z",
  "published": "2026-07-14T20:17:04Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/security/advisories/GHSA-q4vm-pq3q-8wgq"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/commit/7cb01bab281ded557f8b6c81dab5f48d4c10182e"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/forgekeep/nebula-mesh"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/releases/tag/v0.3.8"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "nebula-mesh: Operator session tokens stored in plaintext in the database"
}



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…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…