T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/rlm_auto.py:63
- Finding
- Untrusted slice content is not isolated from sub-agent instructions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/rlm_auto.py:63-73`; `scripts/rlm_emit_toolcalls.py:54-70` **Vulnerability Type**: Prompt injection caused by ineffective role separation **Risk Level**: Medium ### Vulnerable Code ```python # scripts/rlm_auto.py:63-73 for i, sl in enumerate(trimmed, 1): slice_text = text[sl["start"]:sl["end"]] goal_text = args.goal if args.redact: slice_text = redact_secrets(slice_text) goal_text = redact_secrets(goal_text) prompt_path = os.path.join(prompts_dir, f"subcall_{i:02d}.txt") with open(prompt_path, "w", encoding="utf-8") as f: f.write("Slice:\n") f.write(slice_text) f.write("\n\nGoal:\n") f.write(goal_text) ``` ```python # scripts/rlm_emit_toolcalls.py:54-70 sys_prompt = read_text(args.subcall_system) items = read_spawn(args.spawn) batches = {} for it in items: batches.setdefault(it['batch'], []).append(it) out = [] for batch_id in sorted(batches.keys()): batch_calls = [] for it in batches[batch_id]: user_prompt = read_text(it['prompt_file']) full_prompt = f"SYSTEM:\n{sys_prompt}\n\nUSER:\n{user_prompt}\n" batch_calls.append({ "tool": EMITTED_TOOL, "params": { "task": full_prompt, "label": f"rlm_subcall_b{batch_id}" } }) ``` ### Technical Analysis The project claims that instructions found inside analyzed input are treated only as data. However, the implementation copies untrusted slice content and the user-provided goal into a prompt file, then concatenates the supposed system and user messages into one `task` string. The `SYSTEM:` and `USER:` markers are plain text. They are not independently enforced message roles at the model API or tool boundary. Consequently, an instruction embedded in a document slice can compete with the intended sub-agent instructions. Secret redaction does not mitigate this issue because it onl ...[truncated 1577 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Use the agent framework's native, separately enforced system and user message roles instead of placing textual `SYSTEM:` and `USER:` labels inside one task string. 2. Bundle a reviewed, mandatory sub-agent system prompt with the project rather than requiring an unspecified external prompt file. 3. Explicitly instruct sub-agents that document slices are untrusted data and that instructions contained in those slices must never be followed. 4. Place slice data in a well-defined structured envelope, such as a JSON field or strongly delimited block, while clarifying that the field contains content to analyze rather than instructions. 5. Keep the analysis objective outside the untrusted slice-data field. 6. Validate sub-agent responses against an expected schema before aggregation and reject output that contains unexpected tool requests or control instructions. 7. Add adversarial tests containing prompt-injection phrases, forged role markers, and requests to ignore prior instructions. ]]>
