Skip to content

fix(agents/subagents): read SPAWN_ALLOWLIST env var as allowlist fallback (#79490)#80709

Closed
MilosM348 wants to merge 1 commit into
openclaw:mainfrom
MilosM348:fix/spawn-allowlist-env-fallback-79490
Closed

fix(agents/subagents): read SPAWN_ALLOWLIST env var as allowlist fallback (#79490)#80709
MilosM348 wants to merge 1 commit into
openclaw:mainfrom
MilosM348:fix/spawn-allowlist-env-fallback-79490

Conversation

@MilosM348

Copy link
Copy Markdown

Real Behavior Proof

Issue: #79490subagents.allowAgents is the only documented way to allow sessions_spawn in non-default agents, but Docker / Coolify deployments configure agents purely through env vars (AGENTS=[…], no per-agent JSON). With no subagents.allowAgents in agents.defaults and no per-agent override, resolveSubagentTargetPolicy falls through to allowed: none, and every sessions_spawn returns not in allowlist even though the operator clearly intended to opt in.

Reproduction (current main, before this PR):

  1. Boot openclaw with no per-agent config and no agents.defaults.subagents.allowAgents.
  2. Set AGENTS=["primary","reviewer"] and (try to) opt in via SPAWN_ALLOWLIST=*.
  3. Have primary call sessions_spawn { agent: "reviewer" }.

subagent-target-policy.ts resolves:

const policy = resolveSubagentTargetPolicy({
  target,
  agents: cfg.agents?.list,
  allowAgents: resolveAgentConfig(cfg.agents, parentAgentId)
    ?.subagents?.allowAgents
    ?? cfg.agents?.defaults?.subagents?.allowAgents,
});

Both lookups are undefined, so effectiveAllowAgents collapses to [] and the call rejects with target 'reviewer' not in allowlist (allowed: none) — even though the operator set SPAWN_ALLOWLIST=* on the host.

Fix: add resolveSpawnAllowlistFromEnv(env) (in subagent-target-policy.ts) that parses a comma-separated SPAWN_ALLOWLIST (with * for wildcard, whitespace-trimmed, empty entries dropped, returns undefined when unset/blank), and use it as a final fallback after the per-agent and agents.defaults lookups in:

  • src/agents/subagent-target-policy.ts — exports the helper + env constant.
  • src/agents/acp-spawn.ts — wires it into the ACP sessions_spawn path.
  • src/agents/subagent-spawn.ts — wires it into the generic spawn path.
  • src/agents/tools/agents-list-tool.ts — wires it into agents_list so the listing matches what sessions_spawn will actually accept.

Per-agent subagents.allowAgents and agents.defaults.subagents.allowAgents still take precedence; the env fallback only fires when neither is set.

Tests (src/agents/subagent-target-policy.test.ts):

  • resolveSpawnAllowlistFromEnv returns undefined for unset / blank / comma-only strings.
  • Parses single wildcard *.
  • Parses comma-separated agent IDs with whitespace trimming.
  • End-to-end: resolveSubagentTargetPolicy accepts an unknown target and rejects with not in allowlist when allowlist is provided only via SPAWN_ALLOWLIST env.

Local: npx vitest run src/agents/subagent-target-policy.test.ts src/agents/subagent-spawn.test.ts src/agents/openclaw-tools.subagents.sessions-spawn.allowlist.test.ts src/agents/openclaw-tools.subagents.sessions-spawn.lifecycle.test.ts7 files passed (7), 72 tests passed (72).

Backwards compatibility: purely additive. The env var is read only when subagents.allowAgents is unset at both the per-agent and agents.defaults level, so existing JSON configs are untouched.

Out of scope: documenting SPAWN_ALLOWLIST in the deployment docs — happy to follow up in a docs-only PR if maintainers prefer that path.

Fixes #79490.

…back

Container deployments (Docker / Coolify) that configure agents purely
through env vars previously got 'allowed: none' from sessions_spawn
because subagents.allowAgents was only read from per-agent config or
agents.defaults. Adds resolveSpawnAllowlistFromEnv() that parses a
comma-separated SPAWN_ALLOWLIST (with '*' wildcard support) and wires
it into the spawn target-policy, ACP spawn, and agents_list resolution
paths as a final fallback. Per-agent config and agents.defaults still
take precedence.

Fixes openclaw#79490

Co-authored-by: Cursor <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 11, 2026
@clawsweeper

clawsweeper Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as duplicate/superseded: the same SPAWN_ALLOWLIST/subagent allowlist work is already covered by #79538 and #79913, while this branch lacks after-fix real behavior proof and docs for the new env surface.

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Review details

Best possible solution:

Review and land one canonical env allowlist implementation with docs, tests, and real Docker proof, instead of keeping several overlapping PR branches open.

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

Yes. Source inspection shows current main has no SPAWN_ALLOWLIST reader and the spawn authorization paths only consult config-backed subagents.allowAgents, matching the linked Docker/Coolify symptom.

Is this the best way to solve the issue?

No for this PR as the merge path. The fallback-only direction is plausible, but #79538 already carries the same central fix with docs and broader tests, while this PR lacks real after-fix proof.

Security review:

Security review cleared: No concrete supply-chain issue was found; the diff touches spawn authorization but preserves explicit config precedence, with the remaining policy review now owned by the canonical PR.

What I checked:

Likely related people:

  • Peter Steinberger: Blame and shortlog in the current checkout attribute most central subagent policy, direct spawn, ACP spawn, and agents_list history to this author, including recent sessions_spawn security and validation work. (role: recent area contributor; confidence: high; commits: 5dc7a05f7f2d, bfeadb80b66c, b9aa2d436b75; files: src/agents/subagent-target-policy.ts, src/agents/subagent-spawn.ts, src/agents/acp-spawn.ts)
  • Tyler Yust: Local history shows several recent subagent spawn and accepted-note commits adjacent to the authorization and lifecycle path touched by this PR. (role: recent subagent contributor; confidence: medium; commits: 81b93b9ce04b, fe57bea088c7, c2b6f099c694; files: src/agents/subagent-spawn.ts, src/agents/subagent-target-policy.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 2a6dfbd0342a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: SPAWN_ALLOWLIST environment variable is ignored, preventing agent spawning

1 participant