harden: enforce path-safe subagent IDs at ExtractSpawnedAgentIDs · Entire
harden: enforce path-safe subagent IDs at ExtractSpawnedAgentIDs
b1338e1→main·
Soph·1mo ago·2 files·+12 added/-4 removed
CalculateTotalTokenUsage and ExtractAllModifiedFiles build agent-
Enforce the invariant at the choke point: ExtractSpawnedAgentIDs now drops any ID that fails validation.ValidateAgentID, so every downstream agent-
Not a live vulnerability — the current parser already constrains the ID, so the guard is a no-op for today's inputs and adds no behavior change. No test is added: the guarded branch is unreachable through the real extractor (it can't emit a non-path-safe ID), so a test would only exercise dead input.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
c56a01dc268eView transcript
Changes
2
cmd/entire/cli/agent
claudecode
Mtranscript.go+6/-2
factoryaidroid
Mtranscript.go+6/-2
8 unmodified lines
9
10
11
12
13
14
15
239 unmodified lines
255
256
257
257
258
258
259
260
261
262
263
264
265
8 unmodified lines
"github.com/entireio/cli/cmd/entire/cli/agent"
"github.com/entireio/cli/cmd/entire/cli/transcript"
"github.com/entireio/cli/cmd/entire/cli/validation"
// TranscriptLine is an alias to the shared transcript.Line type.
239 unmodified lines
}
}
// Look for agentId in the text
if agentID := extractAgentIDFromText(textContent); agentID != "" {
// Look for agentId in the text. Drop any ID that isn't path-safe:
// callers build agent-<id>.jsonl from it and read that file, so this
// is the choke point that keeps the path inside subagentsDir,
// independent of extractAgentIDFromText's character handling.
if agentID := extractAgentIDFromText(textContent); agentID != "" && validation.ValidateAgentID(agentID) == nil {
agentIDs[agentID] = block.ToolUseID
}
}
Mcmd/entire/cli/agent/claudecode/transcript.go+6/-2
13 unmodified lines
14
15
16
17
18
19
20
250 unmodified lines
271
272
273
273
274
274
275
276
277
278
279
280
281
13 unmodified lines
"github.com/entireio/cli/cmd/entire/cli/agent"
"github.com/entireio/cli/cmd/entire/cli/transcript"
"github.com/entireio/cli/cmd/entire/cli/validation"
// TranscriptLine is an alias to the shared transcript.Line type.
250 unmodified lines
}
}
Mcmd/entire/cli/agent/factoryaidroid/transcript.go+6/-2