{"id":"GHSA-68f8-9mhj-h2mp","summary":"OpenClaw has a Gateway HTTP /v1/models Route Bypasses Operator Read Scope","details":"\u003e Fixed in OpenClaw 2026.3.24, the current shipping release.\n\n## Summary\n\nThe OpenAI-compatible HTTP endpoint `/v1/models` accepts bearer auth but does not enforce operator method scopes.\n\nIn contrast, the WebSocket RPC path enforces `operator.read` for `models.list`.\n\nA caller connected with `operator.approvals` (no read scope) is rejected for `models.list` (`missing scope: operator.read`) but can still enumerate model metadata through HTTP `/v1/models`.\n\nConfirmed on current `main` at commit `06de515b6c42816b62ec752e1c221cab67b38501`.\n\n## Details\n\nThe WS control-plane path enforces role/scope checks centrally before dispatching methods. For non-admin operators, this includes required method scopes such as `operator.read` for `models.list`.\n\nThe HTTP compatibility path for `/v1/models` performs bearer authorization and then returns model metadata; it does not apply an equivalent scope check.\n\nAs reproduced, a caller with only `operator.approvals` can:\n\n1. connect successfully,\n2. fail `models.list` over WS with `missing scope: operator.read`,\n3. fetch `/v1/models` over HTTP with status 200 and model data.\n\nThis is a cross-surface authorization inconsistency where the stricter WS policy can be bypassed via HTTP.\n\n## Impact\n\n- Callers lacking `operator.read` can still enumerate gateway model metadata through HTTP compatibility routes.\n- Breaks scope model consistency between WS RPC and HTTP surfaces.\n- Weakens least-privilege expectations for operators granted non-read scopes.\n\n## Patch Suggestion\n\n### 1) Enforce read scope on `/v1/models` routes\n\nApply a scope gate equivalent to `models.list` before serving `/v1/models` or `/v1/models/:id`.\n\n### 2) Reuse centralized scope-authorization helper for HTTP compatibility endpoints\n\nUse the same operator scope logic used by WS dispatch (`authorizeOperatorScopesForMethod(...)`) to prevent policy drift.\n\n### 3) Add regression tests\n\nKeep this PoC and add explicit negative/positive controls:\n\n- `operator.approvals` without read is rejected on HTTP `/v1/models`.\n- `operator.read` is accepted on both WS `models.list` and HTTP `/v1/models`.\n\n## Credit\n\nReported by @zpbrent.","aliases":["CVE-2026-35619"],"modified":"2026-04-10T20:05:25.610308Z","published":"2026-03-30T18:41:15Z","database_specific":{"github_reviewed_at":"2026-03-30T18:41:15Z","severity":"MODERATE","cwe_ids":["CWE-284","CWE-863"],"nvd_published_at":"2026-04-10T17:17:04Z","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/openclaw/openclaw/security/advisories/GHSA-68f8-9mhj-h2mp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-35619"},{"type":"WEB","url":"https://github.com/openclaw/openclaw/commit/06de515b6c42816b62ec752e1c221cab67b38501"},{"type":"PACKAGE","url":"https://github.com/openclaw/openclaw"},{"type":"WEB","url":"https://www.vulncheck.com/advisories/openclaw-authorization-bypass-via-http-v1-models-endpoint"}],"affected":[{"package":{"name":"openclaw","ecosystem":"npm","purl":"pkg:npm/openclaw"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2026.3.24"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-68f8-9mhj-h2mp/GHSA-68f8-9mhj-h2mp.json","last_known_affected_version_range":"\u003c= 2026.3.23"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N"},{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"}]}