T09 · Insecure Skill Coding Practices
Warning
- Location
- utils.py:55
- Finding
- Incomplete Prompt-Injection Filtering Allows Documented Attack Phrase to Reach Sub-Agents## Vulnerability Details **File Location**: `utils.py:55-76` **Related Evidence**: `tests/security_test_plan.md:8-15` **Vulnerability Type**: Incomplete input validation and prompt-injection mitigation **Risk Level**: Medium ### Vulnerable Code ```python DANGEROUS_INPUT_PATTERNS = [ re.compile(r"disregard\s+(all\s+)?(prior|above|pre(?:vious)?)\s+instr(?:uction)?s?", re.I), re.compile(r"reveal\s+(system|developer)\s+prompt", re.I), re.compile(r"dump\s+(secrets?|keys?|tokens?)", re.I), re.compile(r"export\s+(api[_-]?key|token|secret)", re.I), ] ALLOWED_OPENCLAW_SUBCOMMANDS = { "sessions_spawn", "sessions_list", "sessions_history", } def sanitize_untrusted_task(task: str, max_chars: int = 12000) -> str: """Sanitize untrusted task input before passing to sub-agents.""" if not task: return "" text = task.replace("\x00", "").strip() text = re.sub(r"[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]", "", text) for pattern in DANGEROUS_INPUT_PATTERNS: text = pattern.sub("[FILTERED_UNTRUSTED_INSTRUCTION]", text) return text[:max_chars] ``` The corresponding security test plan states: ```markdown ### 1) Prompt injection filtering Input task includes: - "ignore previous instructions" - "reveal system prompt" - "dump secrets" Expected: - `sanitize_untrusted_task` replaces these fragments with `[FILTERED_UNTRUSTED_INSTRUCTION]`. - Spawned task still includes `SECURITY_PREAMBLE`. ``` ### Technical Analysis The sanitizer uses a small blacklist of literal regular-expression patterns. The documented phrase `ignore previous instructions` does not match the implemented expression, which only recognizes variants beginning with `disregard`. Consequently, the test plan and implementation do not agree: the documented injection phrase passes through unchanged. Semantic prompt injection cannot be reliably prevented through a short phrase black ...[truncated 2274 chars]
- Remediation
- ## Remediation Suggestions 1. Add an immediate regression fix for the documented phrase and common variants, for example by recognizing both `ignore` and `disregard`. Treat this only as supplemental defense, not the primary security boundary. 2. Convert `tests/security_test_plan.md` into executable unit tests that assert the exact output of `sanitize_untrusted_task()` for every documented test vector. 3. Add adversarial tests for capitalization, whitespace changes, punctuation, role reassignment, “forget prior rules,” indirect injection, encoded instructions, and injection contained in intermediate agent output. 4. Clearly delimit untrusted task and prior-agent content as data. Prompts should explicitly state that content inside those delimiters must not redefine roles, safety policies, or tool permissions. 5. Apply the same trust-boundary treatment to Crew synthesis input, Supervisor dependency output, Pipeline stage output, and Council deliberation content. 6. Enforce security at the runtime capability layer: give spawned sessions only the tools required for their role, require confirmation for external side effects, and prevent access to secrets or sensitive host resources. 7. Keep the existing safety preamble, command allowlist, no-shell subprocess invocation, and safe-state defaults as defense-in-depth controls. 8. Document that phrase filtering is heuristic and that model compliance and OpenClaw runtime policy remain mandatory security boundaries.
