T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/debate_orchestrator_generic.py:160
- Finding
- Untrusted Parameters Are Embedded Directly into Tool-Capable Agent Prompts## Vulnerability Details **File Location**: `scripts/debate_orchestrator_generic.py:160-181`, with vulnerable prompt construction at `scripts/debate_orchestrator_generic.py:282-285`, `344-348`, and `367-375` **Vulnerability Type**: Prompt injection through unsanitized topic and workspace parameters **Risk Level**: High ### Vulnerable Code ```python if runtime == "claude": cmd = [ "claude", "-p", prompt, "--model", model, ] elif runtime == "codex": cmd = [ "codex", "-p", prompt, "--model", model, ] result = subprocess.run( cmd, capture_output=True, text=True, timeout=timeout_sec, ) ``` The prompts passed to these tool-capable runtimes are constructed using caller-controlled values: ```python dispatch_agent( "source_ingest_round_0", f"Execute source-ingest.md: topic={opts.topic}, mode=broad, round=0, " f"depth={opts.depth}, num_queries={num_queries}. " f"Workspace: {workspace}", model_tier="balanced", ) ``` ```python dispatch_agent( f"source_ingest_round_{round_num}", f"Execute source-ingest.md: topic={opts.topic}, mode=focused, " f"round={round_num}, search_focus={search_focus}. Workspace: {workspace}", model_tier="balanced", ) ``` ```python pro_prompt = ( f"Execute debate-turn.md: side=pro, round={round_num}, topic={opts.topic}, " f"mode={opts.mode}, speculation={opts.speculation}, depth={opts.depth}. " f"{prev_round_context}. Workspace: {workspace}" ) con_prompt = ( f"Execute debate-turn.md: side=con, round={round_num}, topic={opts.topic}, " f"mode={opts.mode}, speculation={opts.speculation}, depth={opts.depth}. " f"{prev_round_context}. Workspace: {workspace}" ) ``` ### Technical Analysis The debate topic can originate directly from the command line or from a configuration file. Both the topic and workspace path are interpo ...[truncated 1897 chars]
- Remediation
- ## Remediation Suggestions 1. Pass all parameters in a strict JSON envelope rather than interpolating them into free-form control text. 2. Delimit each untrusted value and explicitly instruct the runtime that content inside those fields is data, not executable instructions. 3. Reject control characters, unexpectedly large topics, and invalid workspace paths before prompt construction. 4. Resolve the workspace to a canonical path and require it to remain under an approved workspace root. 5. Run delegated agents with a restricted working directory and a filesystem allowlist limited to that workspace. 6. Disable shell execution and unrelated tools for roles that only need search, read, and structured write operations. 7. Apply network restrictions and destination allowlists where possible. 8. Log tool operations independently and require confirmation for access outside the workspace. 9. Add adversarial tests containing instruction-like topics to confirm that they remain inert data.
