fix(gateway): preserve device identity for local backend calls with auth mode none#98648
fix(gateway): preserve device identity for local backend calls with auth mode none#98648chenyangjun-xy wants to merge 633 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 1, 2026, 12:24 PM ET / 16:24 UTC. Summary Reproducibility: yes. at source level for the review blocker: the linked report is a token-auth Review metrics: 3 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Recreate or rebase this as a narrow current-main Gateway PR, add token-auth Do we have a high-confidence way to reproduce the issue? Yes at source level for the review blocker: the linked report is a token-auth Is this the best way to solve the issue? No. The auth-none guard split may be plausible cleanup, but the best fix needs a clean current-main branch and coverage/proof for the token-auth subagent path described by the linked issue. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a5e11c0083c5. Label changesLabel changes:
Label justifications:
Evidence reviewedSecurity concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
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
|
…96502) * fix(moonshot): bound video description JSON response reads The Moonshot video description endpoint used an unbounded await res.json() to parse the media understanding response. Route through readProviderJsonResponse (16 MiB cap) to match the bound already in place for other media understanding providers (xai, openrouter). AI-assisted. Co-authored-by: Cursor <[email protected]> * test(moonshot): add bounds and malformed-JSON coverage for video description --------- Co-authored-by: Cursor <[email protected]>
…rd (completes openclaw#93767) (openclaw#93820) * fix(imessage): detect MiniMax mm: namespaced reasoning tags in reflection guard The iMessage reflection guard's THINKING_TAG_RE only matched bare `<think>/<thought>` tags, so MiniMax's `<mm:think>` namespaced reasoning tags (and Anthropic's `antml:` prefix) were not recognized as reflected assistant content. When such reasoning leaked back inbound, the guard treated it as a normal user message instead of dropping it, allowing recursive echo amplification. Accept the known reasoning-tag namespace prefixes `(?:antml:|mm:)?` on the think/thought alternatives, mirroring the shared reasoning-tag contract in src/shared/text/reasoning-tags.ts (PR openclaw#93767). This is the remaining channel-monitor complement of openclaw#93767 for the iMessage path; the optional prefix is a pure recognition enhancement with no change to the bare-tag, code-region exemption, or other reflection patterns. Verified by driving the real detectReflectedContent export: <mm:think>secret</mm:think>visible -> isReflection=true (was false) <think>...</think> -> isReflection=true <think>secret</think> -> isReflection=true (no regression) "thinking about minimax algorithms" -> isReflection=false (no false-positive) `<mm:think>x</mm:think>` in code -> isReflection=false (code exemption kept) * chore: retrigger CI for real behavior proof check * refactor(imessage): tighten reflection guard coverage --------- Co-authored-by: Peter Steinberger <[email protected]>
… sessions.usage (openclaw#94096) * fix(usage): reject inverted startDate-endDate range * chore: retrigger CI for real behavior proof check * refactor(usage): resolve validated date ranges once --------- Co-authored-by: Peter Steinberger <[email protected]>
Expose `core/doctor/auth-profiles` as a default-disabled structured Doctor lint check. This maps the existing auth-profile health diagnostics into structured findings while preserving legacy Doctor repair behavior. The check remains opt-in through `--only core/doctor/auth-profiles` or `--all`; default `doctor --lint` behavior is unchanged. Validation: - focused auth-profile/hints/contribution Vitest passed - changed-file oxfmt and oxlint passed - core tsgo passed - git diff --check passed - exact-head hosted CI/Testbox gates passed Co-authored-by: giodl73-repo <[email protected]>
* fix(mcp): require owner for Claude permission replies * fix(mcp): prove owner-gated permission replies
…law#98142) When no chat DM pairing channels are configured, `openclaw pairing list` (no channel argument) threw `Channel required ... (expected one of: )` with an empty enum that reads like a bug. Users who hit this are usually trying to approve a TUI/device or scope-upgrade request, which lives under `openclaw devices`, not `openclaw pairing` (which only handles chat DM pairing). - Guard the channel hint in help text and errors so an empty channel list no longer renders a bare `()` / `(expected one of: )`. - When no pairing channels exist, redirect to `openclaw devices list` / `openclaw devices approve` instead of failing opaquely. AI-assisted (Claude Code).
* fix(exec): bind windows allowlist execution path * fix(exec): add windows shadow execution proof * fix(exec): preserve wildcard allowlist behavior * fix(exec): correct blocked plan test fixture
Backport of openclaw#97118 to release/2026.6.11. (cherry picked from commit 8346e87)
(cherry picked from commit 0a4d0da)
(cherry picked from commit faa99ee)
(cherry picked from commit 866fc34)
(cherry picked from commit 9c154ff)
(cherry picked from commit 5f4fa97)
(cherry picked from commit 9b703d0)
(cherry picked from commit d377c0f)
(cherry picked from commit cf64cf7)
(cherry picked from commit e085fa1)
…ies (openclaw#97168) * fix(slack): prefer current thread session for inherited outbound replies to avoid delivery-mirror session sprawl * fix(slack): require explicit replyToIsExplicit===false for current-session precedence * fix(slack): canonicalize inherited thread replies --------- Co-authored-by: Peter Steinberger <[email protected]>
…call_end events (openclaw#97769) * fix(plugins): apply output text transforms to toolcall_delta and toolcall_end events toolcall_delta and toolcall_end events bypassed the output replacement pipeline, leaking masked tokens (e.g. PII placeholders) into tool call arguments and external systems. Closes openclaw#97761 * fix(plugins): transform nested tool call arguments in output replacements Add recursive transformToolCallArgumentText to handle strings, arrays, and nested objects in tool call arguments, not just the name field. * fix(plugins): keep tool names unchanged and cover result path - Remove toolCall.name transformation to prevent breaking tool routing - Add arguments transform to stream.result()/done.message via transformContentText for tool-call content blocks * fix(plugins): narrow argument transform to toolCall content blocks only Only transform arguments on content blocks with type=toolCall to avoid touching non-tool-call blocks that happen to have an arguments field. * test(plugins): assert stream.result() tool-call content block is transformed * test(plugins): fix result-path fixture to actually contain toolCall block The previous fixture used makeAssistantMessage('final') which produces a plain text content block, not a toolCall block. The stream.result() assertion was vacuously passing. * style(plugins): fix type cast in result-path test assertion * fix(agents): preserve tool argument transforms after repair * refactor(agents): keep tool transform boundary narrow --------- Co-authored-by: Peter Steinberger <[email protected]>
Dependency GuardThis PR changes dependency-related files. Maintainers should confirm these changes are intentional. Changed files:
Maintainer follow-up:
|
Dependency graph changes are blockedOpenClaw does not accept dependency graph changes through PRs unless a repository admin or security explicitly authorizes the current head SHA. Dependency updates are generated internally by maintainers so external PRs cannot change the resolved graph. Detected dependency graph changes:
Auto-scrub was not attempted because this PR also changes dependency-related files that are not package lockfiles:
Please remove lockfile changes manually if they are not needed. To remove lockfile changes, restore them from the target branch: git fetch origin
git checkout 'origin/main' -- 'extensions/acpx/npm-shrinkwrap.json' 'extensions/amazon-bedrock-mantle/npm-shrinkwrap.json' 'extensions/amazon-bedrock/npm-shrinkwrap.json' 'extensions/anthropic-vertex/npm-shrinkwrap.json' 'extensions/arcee/npm-shrinkwrap.json' 'extensions/brave/npm-shrinkwrap.json' 'extensions/cerebras/npm-shrinkwrap.json' 'extensions/chutes/npm-shrinkwrap.json' 'extensions/clickclack/npm-shrinkwrap.json' 'extensions/cloudflare-ai-gateway/npm-shrinkwrap.json' 'extensions/codex/npm-shrinkwrap.json' 'extensions/cohere/npm-shrinkwrap.json' 'extensions/copilot/npm-shrinkwrap.json' 'extensions/deepinfra/npm-shrinkwrap.json' 'extensions/deepseek/npm-shrinkwrap.json' 'extensions/diagnostics-otel/npm-shrinkwrap.json' 'extensions/diagnostics-prometheus/npm-shrinkwrap.json' 'extensions/diffs-language-pack/npm-shrinkwrap.json' 'extensions/diffs/npm-shrinkwrap.json' 'extensions/discord/npm-shrinkwrap.json' 'extensions/exa/npm-shrinkwrap.json' 'extensions/feishu/npm-shrinkwrap.json' 'extensions/firecrawl/npm-shrinkwrap.json' 'extensions/fireworks/npm-shrinkwrap.json' 'extensions/gmi/npm-shrinkwrap.json' 'extensions/google-meet/npm-shrinkwrap.json' 'extensions/googlechat/npm-shrinkwrap.json' 'extensions/gradium/npm-shrinkwrap.json' 'extensions/groq/npm-shrinkwrap.json' 'extensions/inworld/npm-shrinkwrap.json' 'extensions/irc/npm-shrinkwrap.json' 'extensions/kilocode/npm-shrinkwrap.json' 'extensions/kimi-coding/npm-shrinkwrap.json' 'extensions/line/npm-shrinkwrap.json' 'extensions/llama-cpp/npm-shrinkwrap.json' 'extensions/lobster/npm-shrinkwrap.json' 'extensions/matrix/npm-shrinkwrap.json' 'extensions/mattermost/npm-shrinkwrap.json' 'extensions/memory-lancedb/npm-shrinkwrap.json' 'extensions/moonshot/npm-shrinkwrap.json' 'extensions/msteams/npm-shrinkwrap.json' 'extensions/nextcloud-talk/npm-shrinkwrap.json' 'extensions/nostr/npm-shrinkwrap.json' 'extensions/openshell/npm-shrinkwrap.json' 'extensions/parallel/npm-shrinkwrap.json' 'extensions/perplexity/npm-shrinkwrap.json' 'extensions/pixverse/npm-shrinkwrap.json' 'extensions/qianfan/npm-shrinkwrap.json' 'extensions/qqbot/npm-shrinkwrap.json' 'extensions/qwen/npm-shrinkwrap.json' 'extensions/raft/npm-shrinkwrap.json' 'extensions/searxng/npm-shrinkwrap.json' 'extensions/signal/npm-shrinkwrap.json' 'extensions/slack/npm-shrinkwrap.json' 'extensions/sms/npm-shrinkwrap.json' 'extensions/stepfun/npm-shrinkwrap.json' 'extensions/synology-chat/npm-shrinkwrap.json' 'extensions/tavily/npm-shrinkwrap.json' 'extensions/tencent/npm-shrinkwrap.json' 'extensions/tlon/npm-shrinkwrap.json' 'extensions/tokenjuice/npm-shrinkwrap.json' 'extensions/twitch/npm-shrinkwrap.json' 'extensions/venice/npm-shrinkwrap.json' 'extensions/vercel-ai-gateway/npm-shrinkwrap.json' 'extensions/voice-call/npm-shrinkwrap.json' 'extensions/whatsapp/npm-shrinkwrap.json' 'extensions/zai/npm-shrinkwrap.json' 'extensions/zalo/npm-shrinkwrap.json' 'extensions/zalouser/npm-shrinkwrap.json' 'npm-shrinkwrap.json' 'pnpm-lock.yaml'
git commit -m 'chore: remove dependency lockfile change'
git pushIf this PR intentionally needs a dependency graph change, ask a repository admin or member of The action will approve the current head SHA ( |
What This Problem Solves
Fixes #98614:
sessions_spawnfails withmissing scope: operator.writewhen auth mode is"none"(e.g., Google Chat loopback deployments).Root Cause
Commit
65b460f234addedallowAuthNonetoshouldOmitDeviceIdentityForGatewayCall, conflating two separate concerns:requireLocalBackendSharedAuthBoth were gated on
omitDeviceIdentity, so changing one implicitly affected the other.Fix
Separate the two concerns cleanly:
hasLocalBackendSharedAuth: auth mode"none"satisfies the shared-auth requirement independently — no error thrownallowAuthNoneinshouldOmitDeviceIdentityForGatewayCall: auth-none triggers device-identity omission —deviceIdentity = null— so the server-sideshouldSkipLocalBackendSelfPairingbypass preserves requested scopesChanges
src/gateway/call.ts: KeepallowAuthNoneparameter inshouldOmitDeviceIdentityForGatewayCall; introduce separatehasLocalBackendSharedAuthcheck decoupled from device identity omissionsrc/gateway/call.test.ts: Update auth-none test to expect device-less behavior (deviceIdentity.toBeNull())Evidence
Verification environment
Before fix (original PR commit
04a1fcd)auth mode "none" + requireLocalBackendSharedAuth=true
→ allowAuthNone removed from shouldOmitDeviceIdentityForGatewayCall
→ omitDeviceIdentity = false (auth-none no longer triggers omission)
→ deviceIdentity = LOADED (identity-bearing)
→ Test: expect(deviceIdentity).not.toBeNull() ✓
Problem: identity-bearing auth-none can trigger paired-device scope checks
on the server side, bypassing shouldSkipLocalBackendSelfPairing.
After fix (codex-reviewed commit
a2a98ac)auth mode "none" + requireLocalBackendSharedAuth=true
→ allowAuthNone = true
→ hasLocalBackendSharedAuth = true (auth check passes)
→ omitDeviceIdentity = true (device identity omitted)
→ deviceIdentity = null (device-less)
→ Test: expect(deviceIdentity).toBeNull() ✓
server-side shouldSkipLocalBackendSelfPairing → clearUnboundScopes skipped
→ scopes survive handshake → operator.write preserved
Test results
Before fix: Test Files 3 passed | Tests 342 passed
After fix: Test Files 3 passed | Tests 342 passed
Behavioral comparison
allowAuthNoneparamomitDeviceIdentityhasLocalBackendSharedAuthnot.toBeNull()(identity-bearing)toBeNull()(device-less)User Impact
sessions_spawnmulti-agent delegation