fix(agents): add strict format validation to sessions_spawn for agentId#31381
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 572b547cac
ℹ️ 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".
Greptile SummaryThis PR implements a focused security fix that prevents malformed Key changes:
Observations:
Confidence Score: 5/5
Last reviewed commit: 572b547 |
572b547 to
06b30be
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06b30be712
ℹ️ 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".
src/agents/subagent-spawn.ts
Outdated
| // Without this gate, error-message strings like "Agent not found: xyz" pass | ||
| // through normalizeAgentId and become "agent-not-found--xyz", which later | ||
| // creates ghost workspace directories and triggers cascading cron loops (#31311). | ||
| if (requestedAgentId && !STRICT_AGENT_ID_RE.test(requestedAgentId)) { |
There was a problem hiding this comment.
Accept allowlisted normalized IDs before hard-failing
This pre-normalization regex gate rejects some agent IDs that the rest of the codebase already treats as valid normalized IDs, so sessions_spawn can now fail on IDs users are explicitly told to use from agents_list. In particular, IDs like _worker are still producible and persisted via normalization, but this check returns Invalid agentId before allowlist resolution, which is a behavior regression for existing configs. Fresh evidence: normalizeAgentId fallback can preserve leading underscores (src/routing/session-key.ts:91-99), agents add stores that normalized value (src/commands/agents.commands.add.ts:87-95), and agents_list returns normalized IDs from config/allowlists (src/agents/tools/agents-list-tool.ts:57-88).
Useful? React with 👍 / 👎.
Implements a strict format validation for the agentId parameter in sessions_spawn to fully resolve the ghost workspace creation bug reported in openclaw#31311. This fix introduces a regex format gate at the entry point to immediately reject malformed agentId strings. This prevents error messages (e.g., 'Agent not found: xyz') or path traversals from being mangled by normalizeAgentId into seemingly valid IDs (e.g., 'agent-not-found--xyz'), which was the root cause of the bug. The validation is placed before normalization and does not interfere with existing workflows, including delegating to agents that are allowlisted but not globally configured. New, non-redundant tests are added to sessions-spawn.allowlist.test.ts to cover format validation and ensure no regressions in allowlist behavior. Fixes openclaw#31311
06b30be to
4c4c76a
Compare
|
Landed via temp rebase onto main.
Thanks @openperf! |
* main: (174 commits) refactor(gateway): unify control-ui and plugin webhook routing fix(exec): resolve PATH key case-insensitively for Windows pathPrepend (openclaw#25399) (openclaw#31879) fix(tsgo): unblock baseline type errors (openclaw#31873) fix(security): harden sms.send dangerous-node defaults fix(gateway): let POST requests pass through root-mounted Control UI to plugin handlers fix(browser): fail closed navigation guard with env proxy test(perf): reduce timer teardown overhead in cron issue regressions refactor: split browser context/actions and unify CDP timeout policy test(perf): cache redact hints and tune guardrail scan concurrency docs(changelog): credit sessions_spawn agentId validation fix (openclaw#31381) fix(agents): validate sessions_spawn agentId format (openclaw#31381) fix(agents): add strict format validation to sessions_spawn for agentId fix(logging): log timestamps use local time instead of UTC (openclaw#28434) test(perf): remove redundant module reset in system presence version tests test(perf): avoid module reload churn in config guard tests fix(gateway): fail closed plugin auth path canonicalization docs(changelog): credit sandbox mkdirp boundary fix (openclaw#31547) fix(sandbox): allow mkdirp boundary checks on existing directories (openclaw#31547) fix(sandbox): allow mkdirp boundary check on existing directories fix: preserve dns pinning for strict web SSRF fetches ...
This PR resolves #31311 by implementing a strict format validation for the
agentIdparameter insessions_spawn, preventing the creation of ghost workspace directories from malformed inputs.The Problem
When
sessions_spawnreceives an error message string (e.g., from a failed upstream tool call) as theagentId,normalizeAgentIdmangles it into a seemingly valid ID (e.g.,"Agent not found: xyz"becomes"agent-not-found--xyz"). This leads to the creation of an unexpected workspace directory, causing issues like cascading cron failures.The Solution
This fix introduces a strict regex format gate (
/^[a-z0-9][a-z0-9_-]{0,63}$/i) applied to the rawagentIdinput beforenormalizeAgentIdis called. This immediately rejects any malformed strings containing spaces, colons, path separators, or other invalid characters, fixing the bug at its root.Key Design Decisions
configured: falseinagents_list).sessions-spawn.allowlist.test.tsto validate the format gate and ensure no regressions in allowlist behavior.Changes
src/agents/subagent-spawn.tsSTRICT_AGENT_ID_REconstant and format validation...sessions-spawn.allowlist.test.tsFixes #31311