fix(agents): enforce subagent envelope inheritance on ACP child sessions [AI-assisted]#69383
fix(agents): enforce subagent envelope inheritance on ACP child sessions [AI-assisted]#69383pgondhi987 merged 16 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR closes a security gap where ACP child sessions ( Confidence Score: 5/5Safe to merge — the restriction tightening is correct and the logic is consistent with the existing subagent-spawn path. All three tool-policy call sites and the ACP spawn path have been updated symmetrically. The isStoredSubagentEnvelopeSession traversal correctly handles direct subagent keys (early return), ACP keys with patched subagent fields, and ACP keys reachable via the spawnedBy chain — with a cycle guard. Depth, child-count, and allowAgents enforcement in resolveAcpSubagentEnvelopeState mirrors the existing spawnSubagentDirect guards. The previously flagged store-read concerns were resolved in an earlier commit. No remaining findings rise above P2. No files require special attention. Reviews (2): Last reviewed commit: "address build faiure" | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bac38bfb04
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
martingarramon
left a comment
There was a problem hiding this comment.
Security reasoning is sound — ACP children bypassing the subagent deny list + depth/child/allowAgents caps is a real gap, and the isSubagentEnvelopeSession + spawnedBy-chain traversal (with visited-set for cycle safety) is the right shape. Test coverage across the three tool-policy call sites and the ACP spawn gate is solid.
Two blockers + one concern on the hot path before this can land.
1. BLOCKER — TS2345 at src/agents/acp-spawn.ts:267
CI check-additional-extension-surfaces + cascades are red on:
src/agents/acp-spawn.ts(267,36): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
Type 'undefined' is not assignable to type 'string'.
The Boolean(childSessionKey) && !trackedChildSessionKeys.has(childSessionKey) pattern fails because Boolean(...) in TypeScript returns boolean but does NOT narrow the surrounding scope — so childSessionKey stays string | undefined when passed to Set.has(value: string). Drop the Boolean() wrapper; a plain truthy check narrows:
childSessionKey && !trackedChildSessionKeys.has(childSessionKey)(Or typeof childSessionKey === "string" if you want to be explicit.) pnpm tsgo:prod doesn't run the plugin-sdk boundary dts check that caught this; pnpm build does. Running pnpm build locally before push would have surfaced it.
2. BLOCKER — Architectural boundary violation: task-boundaries.test.ts
FAIL src/tasks/task-boundaries.test.ts > task boundaries > keeps direct task-registry imports behind the approved task access seams
AssertionError: expected [ 'agents/acp-spawn.ts', …(3) ] to deeply equal [ 'tasks/runtime-internal.ts', …(2) ]
The new import { listTasksForOwnerKey } from "../tasks/task-registry.js" in acp-spawn.ts crosses an architectural boundary that the codebase enforces via task-boundaries.test.ts. Two options:
- If the direct import is intentional (e.g., security hardening justifies a new seam through task-registry): update the test's approved-seam allowlist to include
agents/acp-spawn.tsand note the rationale in the same commit. The test explicitly expects changes to come with a paired allowlist update. - If the call can route through an existing approved accessor (
tasks/runtime-internal.tsor similar): prefer that — keeps the boundary narrow and matches the existing subagent-spawn path's lookup approach.
Worth flagging to a maintainer which side they prefer before pushing — the boundary test exists to force that conversation.
3. Greptile P2 is valid — hot-path store reads
Greptile flagged that isSubagentEnvelopeSession now reads the session store from three tool-policy call sites (pi-tools.ts:393, effective-tool-policy.ts:137, gateway/tool-resolution.ts:64-66) that were previously pure string checks. For non-subagent ACP sessions (the common case), every resolveGatewayScopedTools call now pays an extra store read that returns undefined and is discarded.
Two cheap options:
- Pass a pre-loaded
storehandle through callers that already have one, so the recursivespawnedBytraversal re-uses the same in-memory map instead of issuing fresh reads at each level. - Add a short-lived request-scoped cache keyed on
childSessionKeyforisSubagentEnvelopeSession— the result is stable within a single tool resolution.
Not a correctness issue, but on a ~5k-contributor repo where resolveGatewayScopedTools runs on every tool call, the I/O shift is worth flagging in the PR body so maintainers can decide.
Minor
- [AI-assisted] + "No human runtime verification was performed" — elevated-risk review mode for a 631-line security-path change. Worth adding a human-verified live repro (subagent → ACP spawn → confirm tool deny list applies) to the Human Verification section before merge, even if the unit tests are comprehensive. Static analysis didn't catch either CI blocker above, so the "static analysis confirms consistency" claim needs a runtime anchor.
- Good call on extracting
DEFAULT_SUBAGENT_MAX_CHILDREN_PER_AGENTto a constant — gives the ACP path and subagent path a single source of truth.
Happy to re-review after the two CI blockers clear and the hot-path question gets a maintainer call.
|
@codex review |
|
@greptile review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb585d7e87
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a98723fd7b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddaaf8972c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01b073e0a5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4adbfbe3e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6e5dbdc66
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
There was a problem hiding this comment.
💡 Codex Review
https://github.com/openclaw/openclaw/blob/2147ce103a3efe32a25e949bf916e5aeaedde19d/src/plugins/status.ts#L193-L197
Forward logger to metadata snapshot loading path
buildPluginSnapshotReport now accepts a caller logger (used by plugins list --json to keep output machine-readable), but the snapshot branch in buildPluginReport drops it when calling loadPluginMetadataRegistrySnapshot. In this path the loader falls back to the default plugin logger, so plugin warnings/info can still be emitted during JSON mode and corrupt stdout JSON for automation. Pass params?.logger through this call so snapshot and diagnostics paths behave consistently.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2147ce103a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
* 'main' of https://github.com/openclaw/openclaw: fix(agents): enforce subagent envelope inheritance on ACP child sessions [AI-assisted] (openclaw#69383) fix(tui): arm streaming watchdog on every delta, not only visible ones (openclaw#69338) fix(codex): exclude codex-app-server synthetic apiKey from secrets audit (openclaw#69581)
|
Re-review Blockers from prior review: both resolved.
Two remaining concerns:
Core subagent envelope path (`acp-spawn.ts` + `gateway/tool-resolution.ts` + `pi-tools.policy.ts` + `subagent-capabilities`) LGTM on intent pending CI green. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31160dc069
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const activeChildren = | ||
| countActiveRunsForSession(requesterSessionKey) + | ||
| countUntrackedActiveAcpRunsForOwner(requesterSessionKey); |
There was a problem hiding this comment.
Make ACP child-cap enforcement independent of task write success
This new cap check depends on countUntrackedActiveAcpRunsForOwner(...), which reads ACP children from task rows, but ACP task registration is still best-effort (createRunningTaskRun(...) exceptions are logged and ignored later in spawnAcpDirect). If task persistence fails (or is transiently unavailable), active ACP children are omitted from this count and subagent-envelope sessions can continue spawning beyond maxChildrenPerAgent, bypassing the policy this change is meant to enforce.
Useful? React with 👍 / 👎.
…ons [AI-assisted] (openclaw#69383) * fix: address issue * fix: address review feedback * fix: finalize issue changes * fix: address PR review feedback * address build faiure * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback
…ons [AI-assisted] (openclaw#69383) * fix: address issue * fix: address review feedback * fix: finalize issue changes * fix: address PR review feedback * address build faiure * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback
…ons [AI-assisted] (openclaw#69383) * fix: address issue * fix: address review feedback * fix: finalize issue changes * fix: address PR review feedback * address build faiure * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback
…ons [AI-assisted] (openclaw#69383) * fix: address issue * fix: address review feedback * fix: finalize issue changes * fix: address PR review feedback * address build faiure * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback
…ons [AI-assisted] (openclaw#69383) * fix: address issue * fix: address review feedback * fix: finalize issue changes * fix: address PR review feedback * address build faiure * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address PR review feedback
Summary
agent:{id}:acp:{uuid}) were not recognized as subagent-envelope sessions byisSubagentSessionKey, so subagent tool policy, spawn-depth caps, per-parent child caps, and thesubagents.allowAgentstarget allowlist were all skipped for ACP children spawned from within a subagent envelope.sessions_send,agents_list), and bypass depth/child/allowlist caps — all while still running inside the same trusted gateway.isSubagentEnvelopeSession(replacing bareisSubagentSessionKeyin three tool-policy call sites) to transitively detect ACP sessions parented by a subagent envelope via thespawnedBychain. AddedresolveAcpSubagentEnvelopeStateto run depth, child-count, andallowAgentschecks on the ACP spawn path and patchspawnDepth/subagentRole/subagentControlScopeonto the child session record. ExtractedDEFAULT_SUBAGENT_MAX_CHILDREN_PER_AGENTconstant.isSubagentSessionKeyitself, ACP approval/allowlist classification, sandbox inheritance, per-sender authorization checks, oracp.allowedAgentsdefault behavior.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
isSubagentSessionKeymatches only keys with asubagent:rest segment. ACP child keys useacp:{uuid}and fell through, sopi-tools.ts,effective-tool-policy.ts, andgateway/tool-resolution.tsall skippedresolveSubagentToolPolicyForSessionfor them. The ACP spawn path inacp-spawn.tsalso never ran the depth/child/allowAgents guards fromsubagent-spawn.ts.Regression Test Plan (if applicable)
src/agents/acp-spawn.test.ts,src/agents/pi-tools.create-openclaw-coding-tools.test.tsUser-visible / Behavior Changes
subagents.maxSpawnDepth,subagents.maxChildrenPerAgent, andsubagents.allowAgentsnow apply to ACP spawns from subagent sessions (previously they applied only toruntime="subagent"spawns).DEFAULT_SUBAGENT_MAX_CHILDREN_PER_AGENTis now an exported constant (default value unchanged:5).Security Impact (required)
Repro + Verification
Environment
Steps
pnpm installpnpm test src/agents/acp-spawn.test.tspnpm test src/agents/pi-tools.create-openclaw-coding-tools.test.tspnpm tsgo:prodExpected
Actual
Evidence
acp-spawn.test.tscases and one newpi-toolsintegration case, all green on branch.Human Verification (required)
isSubagentEnvelopeSessionreturns false for them and the spawn-time gate exits early.Review Conversations
Compatibility / Migration
Risks and Mitigations
runtime="subagent"spawn behavior.