REQ-F-062: Glob Expansion and Word-Splitting Prevention
Tier: Framework-Automatic | Priority: P0
Source: §51 Shell Word Splitting and Glob Expansion Interference
Addresses: Severity: High / Token Spend: Medium / Time: Medium / Context: Low
Description
The framework's subprocess API MUST always invoke external processes using array-form argument lists, never via shell string interpolation. The framework MUST raise a registration error if a command handler passes a shell-string (single joined string) to the subprocess API instead of an argument array. This prevents the shell from performing word-splitting on arguments containing spaces and glob expansion on arguments containing *, ?, or [. When the framework logs subprocess invocations (in debug mode), it MUST display the array form to make quoting visible.
Acceptance Criteria
- An argument containing spaces (e.g.,
"hello world") is received by the subprocess as a single argument, not split into two - An argument containing
*(e.g.,"*.json") is passed literally to the subprocess, not expanded by the shell - Passing a shell-string to the subprocess API raises a framework
SHELL_STRING_PROHIBITEDerror at registration time - In debug mode, subprocess invocations are logged as JSON arrays:
["git", "commit", "-m", "hello world"]
Schema
No dedicated schema type — this requirement governs subprocess invocation behavior without adding new wire-format fields.
Wire Format
No wire-format fields — this requirement governs framework behavior only.
Example
Framework-Automatic: no command author action needed. The framework's exec API only accepts argument arrays; shell-string invocations are rejected at registration time.
# Correct — array form
framework.exec(["git", "commit", "-m", "hello world"])
→ git receives one argument: "hello world"
# Rejected — shell string
framework.exec("git commit -m hello world")
→ FrameworkError: SHELL_STRING_PROHIBITED — pass an argument array, not a shell string
# Argument with glob — passed literally
framework.exec(["find", ".", "-name", "*.json"])
→ find receives literal "*.json"; shell does not expand it
Related
| Requirement | Tier | Relationship |
|---|---|---|
| REQ-F-044 | F | Composes: argument escaping enforcement complements array-form prevention |
| REQ-F-030 | F | Composes: child process tracking applies to all subprocesses spawned via the array API |
| REQ-F-065 | F | Composes: pipeline exit propagation depends on the framework controlling subprocess invocation |
| REQ-F-066 | F | Composes: locale normalization is injected into the same subprocess environment |