fix(security): re-port webchat compaction + conversation-hook access guards (#2764)#2767
Merged
alexey-pelykh merged 1 commit intoJul 2, 2026
Conversation
…guards (#2764) Re-port two medium-severity upstream security fixes missed in the v2026.4.24 content-only sync — both apply to kept fork paths (gateway, plugins) and were advertised/expected controls that were absent live. - gateway: block webchat clients from sessions.compact. Extend rejectWebchatSessionMutation to the "compact" action and guard the handler (client + isWebchatConnect), mirroring sessions.patch/delete. Upstream 873dce1 (PR openclaw#70716). The fork has no sessions.restore handler, so only "compact" is ported (not upstream's "restore"). - plugins: enforce plugins.entries.*.hooks.allowConversationAccess. Add isConversationHookName and gate conversation hooks (llm_input, llm_output, agent_end) in registerTypedHook so non-bundled plugins must opt in explicitly; bundled plugins stay allowed unless they set it false. The config field was fully plumbed but inert. Upstream 51f9f94 (PR openclaw#70786) — registry/hooks portion only. Tests: extend the webchat-mutation gateway test to assert compact is rejected; add a conversation-access gate suite to plugins dead-hooks.test.ts (non-bundled block, opt-in allow, bundled default, bundled opt-out, non-conversation-hook not gated). Co-Authored-By: Claude Opus 4.8 <[email protected]>
alexey-pelykh
deleted the
fix/2764-webchat-compact-conversation-hook-guards
branch
July 2, 2026 12:37
This was referenced Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Re-ports the two Priority-1 Medium security fixes identified in #2764 — advertised/expected controls that were absent on live fork paths after the v2026.4.24 content-only sync. Both apply to kept fork layers (gateway, plugins).
Scope: medium items only. The Priority-2 Low items in #2764 are intentionally out of scope, so this PR uses Refs, not Closes — #2764 stays open for the low-priority drift.
Item 1 —
sessions.compactwebchat session-mutation guardFile:
src/gateway/server-methods/sessions.ts· Upstream:873dce178de(PR openclaw#70716)sessions.patch/sessions.deletecallrejectWebchatSessionMutation;sessions.compactdid not, letting an admin-scoped webchat client (e.g. an XSS'd control-UI session) compact/mutate session transcripts even though the same client class is blocked from patch/delete.rejectWebchatSessionMutationaction union with"compact".sessions.compacttheclient+isWebchatConnecthandler params and call the guard before mutating (mirrors patch/delete).sessions.restorehandler (upstream added"restore"too), so only"compact"is ported — no dead union member.Item 2 — enforce
plugins.entries.*.hooks.allowConversationAccessFiles:
src/plugins/types.ts,src/plugins/registry.ts· Upstream:51f9f94cc36(PR openclaw#70786, registry/hooks portion)The
allowConversationAccessopt-in was fully plumbed and advertised (config schema, normalization, andloader.tspasses it intohookPolicy) but inert —registerTypedHooknever gated on it, so an operator-allowed non-bundled plugin got ungated access to conversation transcripts and the control did nothing.CONVERSATION_HOOK_NAMES(llm_input,llm_output,agent_end) +isConversationHookNametotypes.ts(the fork's equivalent of upstream'shook-types.ts).allowConversationAccesstoPluginTypedHookPolicyand enforced it inregisterTypedHook: non-bundled plugins are blocked unless they set ittrue; bundled plugins stay allowed unless they set itfalse— a diagnostic is pushed on block.status.tshunk is excluded — the fork'sstatus.tshas diverged and surfaces neitherallowPromptInjectionnor the policy block, so porting onlyallowConversationAccessthere would be inconsistent and is outside the stated fix. Thecli-runnertranscript-loading portion of the upstream commit is not part of Re-port upstream security/correctness fixes missed in the v2026.4.24 content-only sync #2764's identified gap.Verification
Both fixes re-verified against #2764's own "verify the gap" steps (gaps confirmed closed):
sessions.compactnow callsrejectWebchatSessionMutation({ action: "compact", … }).isConversationHookNamenow exists and is used;registerTypedHookgates onpolicy?.allowConversationAccess.Tests (added/extended):
src/gateway/server.sessions.gateway-server-sessions-a.test.ts— webchat-mutation test now also assertssessions.compactis rejected (18/18 pass).src/plugins/dead-hooks.test.ts— newconversation hook access gatesuite: non-bundled block, opt-in allow, bundled default-allow, bundled explicit opt-out, non-conversation-hook not gated (7/7 pass).Gates:
pnpm checkgreen (format, tsgo, oxlint 0/0, all fork linters); standalone fork-integrity gates clean (zombie-imports, stub-debt baseline 140==140, throwing-stub-callers 0, no openclaw/lobster leaks).Refs #2764
🤖 Generated with Claude Code