Fixed in OpenClaw 2026.3.24, the current shipping release.
The OpenAI-compatible HTTP endpoint /v1/models accepts bearer auth but does not enforce operator method scopes.
In contrast, the WebSocket RPC path enforces operator.read for models.list.
A 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.
Confirmed on current main at commit 06de515b6c42816b62ec752e1c221cab67b38501.
The 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.
The HTTP compatibility path for /v1/models performs bearer authorization and then returns model metadata; it does not apply an equivalent scope check.
As reproduced, a caller with only operator.approvals can:
models.list over WS with missing scope: operator.read,/v1/models over HTTP with status 200 and model data.This is a cross-surface authorization inconsistency where the stricter WS policy can be bypassed via HTTP.
operator.read can still enumerate gateway model metadata through HTTP compatibility routes./v1/models routesApply a scope gate equivalent to models.list before serving /v1/models or /v1/models/:id.
Use the same operator scope logic used by WS dispatch (authorizeOperatorScopesForMethod(...)) to prevent policy drift.
Keep this PoC and add explicit negative/positive controls:
operator.approvals without read is rejected on HTTP /v1/models.operator.read is accepted on both WS models.list and HTTP /v1/models.Reported by @zpbrent.
{
"nvd_published_at": "2026-04-10T17:17:04Z",
"severity": "MODERATE",
"github_reviewed": true,
"cwe_ids": [
"CWE-284",
"CWE-863"
],
"github_reviewed_at": "2026-03-30T18:41:15Z"
}