Skip to content

feat: add gateway token scopes#81792

Open
steipete wants to merge 2 commits into
mainfrom
codex/gateway-token-scopes
Open

feat: add gateway token scopes#81792
steipete wants to merge 2 commits into
mainfrom
codex/gateway-token-scopes

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Summary

  • Adds gateway.auth.tokenScopes for device-less shared-token WebSocket clients, with read-only/non-loopback rules and privileged opt-in.
  • Applies configured scopes during WebSocket connect, rejects unsafe privileged grants on non-loopback binds, rotates shared-auth sessions when scope policy changes, and documents the contract.
  • Adds schema/help/security-audit/config-baseline coverage and changelog entry.

Fixes #80836
Fixes #81775

Verification

  • pnpm test src/security/audit-gateway-exposure.test.ts src/gateway/auth.test.ts src/gateway/server-methods/config.shared-auth.test.ts src/gateway/server.auth.default-token.test.ts src/gateway/server.auth.control-ui.test.ts src/gateway/server/ws-connection/message-handler.post-connect-health.test.ts src/gateway/server-runtime-config.test.ts src/config/config-misc.test.ts -- --reporter=verbose
  • pnpm config:docs:check
  • git diff --check
  • pnpm check:changed (Blacksmith Testbox tbx_01krk2r04beeam6bbw06sd6gx2, https://github.com/openclaw/openclaw/actions/runs/25856741523)
  • codex-review --mode local; accepted/fixed findings: local Control UI scope preserve gap, live-config privileged-scope guard, config baseline hash; rejected findings: none.

Real behavior proof
Behavior addressed: Trusted headless shared-token WebSocket clients can receive configured static operator scopes such as operator.read without self-granting via params.scopes.
Real environment tested: Local Vitest gateway/config/security suites plus config docs check and Blacksmith Testbox changed gate.
Exact steps or command run after this patch: pnpm test src/security/audit-gateway-exposure.test.ts src/gateway/auth.test.ts src/gateway/server-methods/config.shared-auth.test.ts src/gateway/server.auth.default-token.test.ts src/gateway/server.auth.control-ui.test.ts src/gateway/server/ws-connection/message-handler.post-connect-health.test.ts src/gateway/server-runtime-config.test.ts src/config/config-misc.test.ts -- --reporter=verbose; pnpm config:docs:check; git diff --check; pnpm check:changed.
Evidence after fix: Device-less token tests connect with requested admin/read scopes but receive only operator.read from gateway.auth.tokenScopes, then sessions.messages.subscribe succeeds; local insecure Control UI token clients are similarly bounded; privileged scopes are rejected on non-loopback binds without opt-in.
Observed result after fix: Focused tests passed; config docs check passed; diff check passed; check:changed passed on Blacksmith Testbox tbx_01krk2r04beeam6bbw06sd6gx2.
What was not tested: Full end-to-end third-party client against a deployed Gateway; covered by in-process Gateway WebSocket tests.

@steipete
steipete requested a review from a team as a code owner May 14, 2026 11:12
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime size: M maintainer Maintainer-authored PR labels May 14, 2026
@clawsweeper

clawsweeper Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 3, 2026, 11:51 PM ET / 03:51 UTC.

Summary
The PR adds gateway.auth.tokenScopes and gateway.auth.allowPrivilegedTokenScopes, applies configured scopes to device-less shared-token WebSocket auth, rotates shared-auth sessions on policy changes, and updates config/docs/tests/security audit metadata.

PR surface: Source +246, Tests +172, Docs +53, Generated 0, Other +6. Total +477 across 28 files.

Reproducibility: yes. at source level: current main lacks gateway.auth.tokenScopes, the strict config schema rejects it, and current tests expect device-less shared-token auth to report empty scopes. I did not run a live Gateway reproduction in this read-only pass.

Review metrics: 1 noteworthy metric.

  • Gateway auth config surfaces: 2 added. gateway.auth.tokenScopes and gateway.auth.allowPrivilegedTokenScopes expand the public auth/config contract, so compatibility and security review matter before merge.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/server-methods/config.shared-auth.test.ts, serialized state: src/gateway/server/ws-shared-generation.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted terminal/log/live output from a real Gateway WebSocket client showing tokenScopes grants operator.read and privileged non-loopback grants are rejected without opt-in.
  • Rebase the branch and remove the deleted codex-review skill edits plus the release-owned CHANGELOG.md entry.
  • Get explicit Gateway/security owner approval for the shared-token static-scope contract and upgrade/session-generation behavior.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body provides focused tests, config docs check, diff check, and Testbox CI, but no redacted terminal/log/live output from a real Gateway WebSocket client after the patch. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The PR adds static operator-scope grants for shared-token WebSocket clients, so the trust model and privileged non-loopback opt-in need explicit Gateway/security approval before merge.
  • [P1] The branch is currently conflicting and maintainerCanModify=false, so maintainers cannot review the actual merge result until the contributor refreshes it or opens a successor branch.
  • [P1] The PR body provides tests and CI only; it still lacks redacted real Gateway WebSocket client terminal/log/live output proving tokenScopes behavior after the patch.
  • [P1] The shared-token session-generation input changes for token/password auth, so upgrade behavior and any one-time shared-auth WebSocket disconnect effect should be consciously accepted.
  • [P1] The branch carries unrelated deleted codex-review skill edits and a release-owned CHANGELOG.md entry, both of which add stale review noise to an already compatibility-sensitive auth PR.

Maintainer options:

  1. Refresh And Prove Before Merge (recommended)
    Resolve the conflict, remove stale branch drift, and add redacted real Gateway WebSocket output showing configured read scopes and the privileged non-loopback rejection path.
  2. Approve The Auth Contract
    Gateway/security owners can explicitly accept the shared-token static-scope model, including loopback and privileged-scope semantics, before landing it.
  3. Pause On Product Direction
    If maintainers are not ready to add public auth config fields, keep the design discussion on RFE: gateway.auth.tokenScopes config field for headless/single-tenant deployments #80836 and leave this branch unmerged.

Next step before merge

  • [P1] Manual review only: the protected maintainer label, conflicting uneditable branch, missing real proof, and auth-boundary approval are not safe for autonomous repair.

Security
Needs attention: No dependency or supply-chain issue is visible, but the PR changes the Gateway authorization boundary by letting shared-token config grant operator scopes.

Review findings

  • [P2] Drop the stale codex-review skill edits — .agents/skills/codex-review/SKILL.md:24-25
  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:9
Review details

Best possible solution:

Rebase against current main, remove unrelated/release-owned drift, add redacted real Gateway WebSocket proof, and merge only after Gateway/security owners approve the static token-scope trust boundary and upgrade behavior.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main lacks gateway.auth.tokenScopes, the strict config schema rejects it, and current tests expect device-less shared-token auth to report empty scopes. I did not run a live Gateway reproduction in this read-only pass.

Is this the best way to solve the issue?

Unclear as a merge-ready solution: static configured scopes are a plausible safer path than trusting client-supplied params.scopes, but this branch still needs conflict cleanup, real Gateway proof, and Gateway/security approval.

Full review comments:

  • [P2] Drop the stale codex-review skill edits — .agents/skills/codex-review/SKILL.md:24-25
    Current main no longer has .agents/skills/codex-review and uses .agents/skills/autoreview instead. Keeping these unrelated deleted-file edits in a Gateway auth PR reintroduces stale tooling from the old base and contributes to the conflicting branch state.
    Confidence: 0.9
  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:9
    CHANGELOG.md is release-generated for normal PRs; release-note context belongs in the PR body or squash message. This direct entry is unrelated to implementing the Gateway auth behavior and will create release-changelog churn/conflicts when the branch is refreshed.
    Confidence: 0.82

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 9d68f877ac3e.

Label changes

Label justifications:

  • P2: The PR targets a real Gateway auth/config gap with downstream impact, but it is bounded work rather than an emergency outage.
  • merge-risk: 🚨 compatibility: The PR adds public Gateway auth config fields and changes shared-token session generation/disconnect behavior.
  • merge-risk: 🚨 auth-provider: The diff changes shared-token WebSocket auth semantics and token-authenticated operator clients' effective scopes.
  • merge-risk: 🚨 security-boundary: A configured shared Gateway token can grant operator scopes, including privileged scopes behind explicit opt-in.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body provides focused tests, config docs check, diff check, and Testbox CI, but no redacted terminal/log/live output from a real Gateway WebSocket client after the patch. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +246, Tests +172, Docs +53, Generated 0, Other +6. Total +477 across 28 files.

View PR surface stats
Area Files Added Removed Net
Source 15 251 5 +246
Tests 5 173 1 +172
Docs 6 59 6 +53
Config 0 0 0 0
Generated 1 3 3 0
Other 1 7 1 +6
Total 28 493 16 +477

Security concerns:

  • [medium] Approve static shared-token scope grants — src/config/types.gateway.ts:186
    The new config lets any holder of the shared Gateway token receive configured operator scopes without device pairing; the loopback and privileged-scope guards help, but this trust model needs Gateway/security owner approval and real behavior proof before merge.
    Confidence: 0.88

What I checked:

  • Root policy read: Root AGENTS.md was read fully and applied; its config/auth compatibility, security-boundary, changelog, and protected-label review rules are relevant to this PR. (AGENTS.md:29, 9d68f877ac3e)
  • Scoped policy read: Gateway and docs scoped AGENTS.md files were read fully; they add Gateway hot-path and Mintlify docs constraints for the touched paths. (src/gateway/AGENTS.md:1, 9d68f877ac3e)
  • Live PR state: Live GitHub reports the PR open, not draft, maintainerCanModify=false, mergeable=CONFLICTING, mergeStateStatus=DIRTY, and carrying the protected maintainer label. (1f82f46085fd)
  • Current main lacks config surface: Current GatewayAuthConfig has mode/token/password/Tailscale/rate-limit/trusted-proxy fields and no token-scope fields, so this PR adds public Gateway auth config surface. (src/config/types.gateway.ts:190, 9d68f877ac3e)
  • Current main schema rejects the new fields: The strict gateway.auth zod schema does not include tokenScopes or allowPrivilegedTokenScopes. (src/config/zod-schema.ts:1090, 9d68f877ac3e)
  • Current main clears device-less shared-token scopes: The WebSocket connect handler still clears scopes for device-less clients outside explicit preservation cases. (src/gateway/server/ws-connection/message-handler.ts:1058, 9d68f877ac3e)

Likely related people:

  • steipete: PR commits implement tokenScopes, and prior gateway/auth history in related reviews ties this account to default-token scope baselines and gateway client extraction work. (role: current proposal owner and adjacent area contributor; confidence: high; commits: 82fd88dbf4f3, 1f82f46085fd, b1117d98622f; files: src/gateway/server.auth.default-token.suite.ts, src/gateway/server/ws-connection/message-handler.ts, src/config/types.gateway.ts)
  • vincentkoc: Recent current-main GitHub commit history shows gateway auth handshake/security-event work and prior related reviews identify shared-auth scope-clearing hardening in this path. (role: recent area contributor; confidence: high; commits: 299d31c56ef1, 6f53f84af3e1, 5e389d5e7c92; files: src/gateway/server/ws-connection/message-handler.ts, src/gateway/server.auth.compat-baseline.test.ts, src/gateway/server.auth.control-ui.suite.ts)
  • jacobtomlinson: Commit history for connect-policy.ts shows trusted-proxy unbound-scope clearing through the same missing-device policy helper this PR changes around. (role: adjacent auth-policy contributor; confidence: medium; commits: 8b88b927cb07; files: src/gateway/server/ws-connection/connect-policy.ts, src/gateway/server/ws-connection/message-handler.ts, src/gateway/server/ws-connection/connect-policy.test.ts)
  • joshavant: Recent current-main commit history shows scoped Gateway/cron operation work touching message-handler.ts, an adjacent caller-scope authorization path. (role: recent gateway policy contributor; confidence: medium; commits: cee2aca40912; files: src/gateway/server/ws-connection/message-handler.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

1 participant