fix: keep trusted policies with hook registry#94545
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 20, 2026, 8:17 PM ET / 00:17 UTC. Summary PR surface: Source +89, Tests +228. Total +317 across 9 files. Reproducibility: yes. at source level. Current main composes hook dispatch from live registries while trusted-policy diagnostics and evaluation still read the active registry, and the PR adds focused regression coverage for that split. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land after maintainer security-boundary review confirms the composed trusted-policy semantics, internal getter boundary, and bundled-before-installed ordering are the intended contract. Do we have a high-confidence way to reproduce the issue? Yes, at source level. Current main composes hook dispatch from live registries while trusted-policy diagnostics and evaluation still read the active registry, and the PR adds focused regression coverage for that split. Is this the best way to solve the issue? Yes. Passing the same composed registry into trusted-policy diagnostics and evaluation is the narrow owner-boundary fix; keeping active-registry lookup preserves the split, while exporting the getter through the SDK would widen internal surface unnecessarily. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 6c2c43d63f4c. Label changesLabel justifications:
Evidence reviewedPR surface: Source +89, Tests +228. Total +317 across 9 files. View PR surface stats
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
|
|
The fix direction is right (policies should resolve from the same live registry set as hooks), but in That's ~40 lines of duplicated control flow, which reads as a smell against the repo's "reduce non-test LOC / avoid duplication" bar. A single helper parameterized by the per-source contribution-id sets collapses both: function selectContributionOwners(
sources: TrustedPolicyHookRunnerRegistry[],
contributionIdsBySource: Set<string>[],
): Map<string, number> {
const owner = new Map<string, number>();
const claim = (id: string, i: number) => { if (!owner.has(id)) owner.set(id, i); };
sources.forEach((r, i) => { for (const p of r.plugins) if (p.status === "loaded" && contributionIdsBySource[i].has(p.id)) claim(p.id, i); });
sources.forEach((r, i) => { for (const p of r.plugins) if (p.status === "loaded") claim(p.id, i); });
sources.forEach((r, i) => { for (const p of r.plugins) claim(p.id, i); });
contributionIdsBySource.forEach((ids, i) => { for (const id of ids) claim(id, i); });
return owner;
}Hooks pass the hook-id sets, policies pass the policy-id sets. Purely a dedupe — no behavior change intended. |
* fix: keep trusted policies with hook registry * fix: compose trusted policies with live hooks * fix: preserve trusted policy order * test: update hook runner mock * fix: keep hook policy registry internal
* fix: keep trusted policies with hook registry * fix: compose trusted policies with live hooks * fix: preserve trusted policy order * test: update hook runner mock * fix: keep hook policy registry internal
…26.6.10) (#1256) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.6.9` → `2026.6.10` | --- ### Release Notes <details> <summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary> ### [`v2026.6.10`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#2026610) [Compare Source](openclaw/openclaw@v2026.6.9...v2026.6.10) ##### Highlights - **Automatic fast mode for talks:** OpenClaw can enable fast mode for short conversational turns, then return to normal mode for longer runs with bounded fallback and delivery behavior. ([#​85104](openclaw/openclaw#85104)) Thanks [@​alexph-dev](https://github.com/alexph-dev) and [@​vincentkoc](https://github.com/vincentkoc). - **More reliable model routing:** Zai model synthesis, GLM overload failover, and native reasoning-level selection now follow the active model catalog more consistently. ([#​94461](openclaw/openclaw#94461), [#​93241](openclaw/openclaw#93241), [#​94067](openclaw/openclaw#94067), [#​94136](openclaw/openclaw#94136)) Thanks [@​Pandah97](https://github.com/Pandah97), [@​chrysb](https://github.com/chrysb), [@​0xghost42](https://github.com/0xghost42), [@​zhengli0922](https://github.com/zhengli0922), [@​openperf](https://github.com/openperf), [@​civiltox](https://github.com/civiltox), and [@​BorClaw](https://github.com/BorClaw). - **Safer session and channel state:** channel switches reset stale origin fields, and cron delivery awareness stays attached to the target session. ([#​95328](openclaw/openclaw#95328), [#​93580](openclaw/openclaw#93580)) Thanks [@​ZengWen-DT](https://github.com/ZengWen-DT), [@​jalehman](https://github.com/jalehman), [@​gorkem2020](https://github.com/gorkem2020), and [@​scotthuang](https://github.com/scotthuang). - **Trusted policies survive hook composition:** composed hook registries keep the trusted tool policies required by approval-sensitive flows. ([#​94545](openclaw/openclaw#94545)) Thanks [@​jesse-merhi](https://github.com/jesse-merhi). ##### Changes - **Agent and channel runtime:** fast-mode state now survives retries, fallback transitions, progress events, and embedded/CLI/ACP normalization; session and channel routing retain the current target and delivery context. ([#​85104](openclaw/openclaw#85104), [#​93580](openclaw/openclaw#93580), [#​95328](openclaw/openclaw#95328)) Thanks [@​alexph-dev](https://github.com/alexph-dev), [@​vincentkoc](https://github.com/vincentkoc), [@​scotthuang](https://github.com/scotthuang), [@​ZengWen-DT](https://github.com/ZengWen-DT), [@​jalehman](https://github.com/jalehman), and [@​gorkem2020](https://github.com/gorkem2020). - **Provider behavior:** model catalogs now supply the correct Zai base URL, overload classification, and native reasoning controls for live-discovered models. ([#​94461](openclaw/openclaw#94461), [#​93241](openclaw/openclaw#93241), [#​94067](openclaw/openclaw#94067), [#​94136](openclaw/openclaw#94136)) Thanks [@​Pandah97](https://github.com/Pandah97), [@​chrysb](https://github.com/chrysb), [@​0xghost42](https://github.com/0xghost42), [@​zhengli0922](https://github.com/zhengli0922), [@​openperf](https://github.com/openperf), [@​civiltox](https://github.com/civiltox), and [@​BorClaw](https://github.com/BorClaw). ##### Fixes - **Fast-mode and policy correctness:** fallback cutoffs and reset notices are bounded, repeated progress events remain visible, Codex service-tier state is normalized, and trusted policies are not lost when hook registries are composed. ([#​85104](openclaw/openclaw#85104), [#​94545](openclaw/openclaw#94545)) Thanks [@​alexph-dev](https://github.com/alexph-dev), [@​vincentkoc](https://github.com/vincentkoc), and [@​jesse-merhi](https://github.com/jesse-merhi). - **Model and delivery edge cases:** Zai and GLM failover paths use the right runtime metadata, while stale channel-origin state no longer leaks across session changes. ([#​94461](openclaw/openclaw#94461), [#​93241](openclaw/openclaw#93241), [#​95328](openclaw/openclaw#95328)) Thanks [@​Pandah97](https://github.com/Pandah97), [@​chrysb](https://github.com/chrysb), [@​0xghost42](https://github.com/0xghost42), [@​zhengli0922](https://github.com/zhengli0922), [@​ZengWen-DT](https://github.com/ZengWen-DT), [@​jalehman](https://github.com/jalehman), and [@​gorkem2020](https://github.com/gorkem2020). - **Provider plugin onboarding:** setup refreshes provider plugin registry metadata after installing setup-selected provider plugins, so auth continuation uses the newly installed provider instead of stale registry state. ([#​95792](openclaw/openclaw#95792)) Thanks [@​snowzlmbot](https://github.com/snowzlmbot). ##### Complete contribution record This audited record covers the complete v2026.6.9..HEAD history: 12 merged PRs. The generation manifest also supplies direct commits as editorial input; the grouped notes above prioritize user impact. ##### Pull requests - **PR [#​86627](openclaw/openclaw#86627 Keep core doctor health in contribution order. Thanks [@​giodl73-repo](https://github.com/giodl73-repo). - **PR [#​93580](openclaw/openclaw#93580 fix: preserve cron delivery awareness for target sessions. Thanks [@​scotthuang](https://github.com/scotthuang) and [@​jalehman](https://github.com/jalehman). - **PR [#​95030](openclaw/openclaw#95030 refactor: add SDK transcript identity target API. Thanks [@​jalehman](https://github.com/jalehman). - **PR [#​94838](openclaw/openclaw#94838 refactor(copilot): complete harness lifecycle parity. Thanks [@​vincentkoc](https://github.com/vincentkoc). - **PR [#​95328](openclaw/openclaw#95328 fix(sessions): reset stale per-channel origin fields on channel switch. Related [#​95325](openclaw/openclaw#95325). Thanks [@​ZengWen-DT](https://github.com/ZengWen-DT) and [@​jalehman](https://github.com/jalehman) and [@​gorkem2020](https://github.com/gorkem2020). - **PR [#​94461](openclaw/openclaw#94461 fix(zai): fall back to manifest baseUrl for synthesized GLM-5 models. Related [#​94269](openclaw/openclaw#94269). Thanks [@​Pandah97](https://github.com/Pandah97) and [@​chrysb](https://github.com/chrysb). - **PR [#​93241](openclaw/openclaw#93241 fix(agents): classify Zhipu GLM overload as overloaded for failover. Related [#​93211](openclaw/openclaw#93211). Thanks [@​0xghost42](https://github.com/0xghost42) and [@​zhengli0922](https://github.com/zhengli0922). - **PR [#​94067](openclaw/openclaw#94067 fix(channels): resolve native /think menu levels via runtime catalog for live-discovered models. Related [#​93835](openclaw/openclaw#93835). Thanks [@​openperf](https://github.com/openperf) and [@​civiltox](https://github.com/civiltox). - **PR [#​94136](openclaw/openclaw#94136 fix(zai): expose GLM-5.2 reasoning levels \[AI-assisted]. Thanks [@​BorClaw](https://github.com/BorClaw). - **PR [#​85104](openclaw/openclaw#85104 feat: fast talks auto mode. Related [#​85087](openclaw/openclaw#85087). Thanks [@​alexph-dev](https://github.com/alexph-dev). - **PR [#​94545](openclaw/openclaw#94545 fix: keep trusted policies with hook registry. Thanks [@​jesse-merhi](https://github.com/jesse-merhi). - **PR [#​95792](openclaw/openclaw#95792 fix(onboard): refresh provider plugin registry after setup installs. Related [#​95765](openclaw/openclaw#95765). Thanks [@​snowzlmbot](https://github.com/snowzlmbot). </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/1256
Summary
before_tool_calltrusted-policy lookup so it uses the same composed live plugin registry view as the global hook runner.What Changed
A Gateway run can keep plugin hooks live through the global hook runner while a later scoped/default registry becomes the active registry. Current
maincomposes hook dispatch from the latest initialized registry plus live active/pinned registries. Before this change, trusted policies were still read from a single active/latest registry path, so a hook from a pinned Gateway registry could run while that registry's trusted policy was invisible.The fixed path exposes an internal composed registry view and passes that registry into trusted-policy diagnostics and evaluation.
src/plugins/hook-runner-global.tsstays the public hook-runner module;src/plugins/hook-runner-global-state.tsowns the internal composed-registry state.The composed policy list is owner-filtered across live registries, then ordered by the existing trusted-policy contract: bundled policies first, installed policies after. That matters because trusted-policy blocks are terminal and policy parameter rewrites feed later policies.
Flow
flowchart TD A[Tool call enters before_tool_call path] --> B[Read composed hook-runner registry] B --> C{Trusted policies present?} C -- yes --> D[Run trusted policies from same live registry as hooks] C -- no --> E[Skip trusted policy phase] D --> F{Policy blocks or rewrites?} F -- block --> G[Stop before ordinary hook] F -- rewrite --> H[Pass adjusted params onward] F -- allow --> H E --> H H --> I{before_tool_call hooks present?} I -- yes --> J[Run ordinary plugin hooks] I -- no --> K[Execute tool] J --> KBehavior Addressed
atl-sec-core, later registry becomes activehook-runner-global-state.ts, with guardrail coveragegetGlobalHookRunner()nullfor the internal registry lookup so resolve-exec-env tests stay scopedReal behavior proof
Behavior addressed: split-registry trusted-policy bypass in
runBeforeToolCallHook(...), including the current composed global hook-runner path, trusted-policy ordering across live registries, SDK export boundaries, and the existing exec-env hook path that uses a mocked hook runner.Real environment tested: local OpenClaw worktree on current
origin/main, branchjesse/fix-trusted-policy-registry, commite5314c0272619d109e3c6fd767200c2a6d68d61a.Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix: the before-tool-call tests create a Gateway registry with a trusted policy, replace/reinitialize later registries, and confirm the trusted policy still blocks before the ordinary hook runs. The hook-runner-global tests verify the composed registry exposes the pinned Gateway trusted policy after later initialization and keeps bundled policies before installed policies across live registries. The SDK guardrail test verifies the internal composed-registry getter and trusted-policy field do not leak through the public runtime barrel. The resolve-exec-env test verifies existing before-tool-call mocked-hook coverage still reaches the exec host instead of failing closed on the new registry lookup.
What was not tested: a rebuilt ASSP/RovoClaw container using this patched OpenClaw commit was not run after the code change. Upstream Codex tests were not run; Codex source was inspected for the PreToolUse contract.
Verification