openclaw - ✅(Solved) Fix [Bug] /v1/responses returns 403 missing scope operator.write with valid JWT [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#57331Fetched 2026-04-08 01:50:54
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
1
Participants
Timeline (top)
subscribed ×2commented ×1cross-referenced ×1referenced ×1

Error Message

"error": {

PR fix notes

PR #57889: fix(gateway): preserve operator scopes for token-authenticated non-local clients

Description (problem / solution / changelog)

Summary

Operators authenticated via Tailscale or trusted-proxy lose all declared scopes on connect, causing "missing scope: operator.write" errors. Fixes #51396, #57331, #46997, #48229.

Root cause

handleMissingDeviceIdentity() depends on sharedAuthOk from evaluateMissingDeviceIdentity(). For Tailscale clients, primary auth succeeds (authMethod=tailscale, authOk=true) but the shared auth probe fails because it uses authorizeHttpGatewayConnect with allowTailscale=false. This returns reject-device-required, and clearUnboundScopes() strips all operator scopes.

Fix

Added operatorTransportMismatch guard that returns true early before the decision check and scope clearing. Triggers only when:

  1. role=operator, 2. authOk=true, 3. authMethod=tailscale or trusted-proxy, 4. sharedAuthOk=false, 5. no device

Regular token-authenticated operators are unaffected per existing baseline in server.auth.default-token.suite.ts.

Testing

  • Regression test in connect-policy.test.ts
  • Existing auth tests pass
  • 7 lines added, surgical fix

Changed files

  • src/gateway/server/ws-connection/connect-policy.test.ts (modified, +33/-0)
  • src/gateway/server/ws-connection/message-handler.ts (modified, +16/-0)

Code Example

{
  "error": {
    "type": "forbidden",
    "message": "missing scope: operator.write"
  }
}
RAW_BUFFERClick to expand / collapse

Bug Description

After upgrading to OpenClaw 2026.3.28, HTTP requests to POST /v1/responses and GET /v1/models return HTTP 403 with:

{
  "error": {
    "type": "forbidden",
    "message": "missing scope: operator.write"
  }
}

The JWT in Authorization: Bearer <token> does contain operator.read and operator.write in its scope claim. The token works for all other authenticated operations.

Affected Endpoints

  • POST /v1/responses — Android app SSE streaming and general HTTP clients
  • GET /v1/models — model discovery

What Works

  • Telegram bot authentication
  • WebSocket connections
  • Other paths outside the OpenAI-compatible HTTP /v1/* surface

What Does Not Work

  • Any HTTP client (curl, Python, mobile app) calling /v1/responses or /v1/models with a JWT that has operator.write
  • Android app SSE streaming

trusted-proxy Mode

gateway.trustedProxy: true does not bypass the 403.

Environment

  • OpenClaw version: 2026.3.28
  • Platform: Linux
  • Android app: affected

Related Issues

  • #57231 — Discord DMs duplicate messages (closed, auth-adjacent)
  • #57275 — OAuth login fails with "Failed to extract accountId from token" in TUI (open, auth regression)
  • #55768 — Health check bloat: uptime monitors must use /health not /v1/chat/completions (open)

Relevant Changelog Entries (for reviewers)

  • #22582 (Gateway/Scopes): Added operator.read/operator.write scope bundles for CLI/Control UI/macOS clients to fix pairing required disconnects on loopback gateways. The /v1/responses HTTP path may not have been included in this fix.
  • #23125, #23006 (Gateway/Pairing): Treated operator.admin pairing tokens as satisfying operator.write requests to fix scope-upgrade prompt loops from 2026.2.19.
  • 2026.3.28 #280: "Security/gateway auth: enforce operator.read and models.list on /v1/models" — this explicitly addressed /v1/models but made no mention of /v1/responses, suggesting a parallel gap.

Unreleased Section

The ## Unreleased changelog section contains no entry for /v1/responses auth, indicating no fix is currently filed for this issue.

Expected vs Actual

  • Expected: JWT with operator.writePOST /v1/responses succeeds
  • Actual: HTTP 403 "missing scope: operator.write"

Hypothesis

The scope enforcement introduced in 2026.3.28 for the OpenAI-compatible HTTP surface may be checking the JWT claim incorrectly for /v1/responses, or a parallel operator.write gate was added to /v1/responses without the accompanying scope-bundle update that #22582 applied to other surfaces.

extent analysis

Fix Plan

To resolve the HTTP 403 issue with POST /v1/responses and GET /v1/models endpoints, we need to update the scope enforcement logic.

Here are the steps:

  • Update the Gateway/Scopes to include operator.write scope for the /v1/responses endpoint.
  • Verify that the operator.read and models.list scopes are correctly enforced for the /v1/models endpoint.
  • Ensure that the JWT claim is correctly checked for the required scopes.

Example code snippet to update the scope enforcement:

# Update the scope enforcement logic
def check_scope(endpoint, token_scopes):
    required_scopes = {
        '/v1/responses': ['operator.write'],
        '/v1/models': ['operator.read', 'models.list']
    }
    if endpoint in required_scopes:
        for scope in required_scopes[endpoint]:
            if scope not in token_scopes:
                return False
    return True

Verification

To verify that the fix worked, test the following scenarios:

  • Send a POST request to /v1/responses with a JWT containing operator.write scope.
  • Send a GET request to /v1/models with a JWT containing operator.read and models.list scopes.
  • Verify that the requests return a successful response (200 OK) instead of an HTTP 403 error.

Extra Tips

  • Ensure that the gateway.trustedProxy mode is correctly configured to bypass scope enforcement if necessary.
  • Review the changelog entries and related issues to ensure that all affected endpoints are updated with the correct scope enforcement logic.
  • Test the fix thoroughly to prevent regressions and ensure that the scope enforcement logic is working as expected.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING