T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/clean_drawing.py:208
- Finding
- Untrusted Drawing Text Is Forwarded Verbatim to Downstream AI Systems## Vulnerability Details **File Location**: `scripts/clean_drawing.py:208-220, 266`; related downstream workflow in `SKILL.md:87, 101` **Vulnerability Type**: Indirect prompt-injection exposure through insufficient output sanitization **Risk Level**: Medium ### Vulnerable Code ```python for line in raw_lines: # Remove Markdown formatting symbols cleaned = re.sub(r'^#+\s*', '', line).strip() cleaned = re.sub(r'^-+\s*', '', cleaned).strip() cleaned = re.sub(r'\s*\|\s*', ' ', cleaned) if not cleaned: continue # Split merged fragments segments = [s.strip() for s in cleaned.split(' ') if s.strip()] for seg in segments: if is_noise(seg): continue tag = classify_line(seg) # Deduplicate within each category if seg not in result[tag]: result[tag].append(seg) ``` The retained input is later written verbatim: ```python for tag in priority_order: items = classified.get(tag, []) if not items: continue lines_out.append(f"## [{tag}]\n\n") for item in items: lines_out.append(f"- {item}\n") lines_out.append("\n") ``` The documented workflow then supplies this output to another AI system: ```markdown boq-generator skill ``` `SKILL.md:101` also recommends sending content from the catch-all category to a language model for summarization before passing it to `boq-generator`. ### Technical Analysis The input Markdown represents text extracted from potentially untrusted drawing files. The cleaning process removes only a small set of Markdown prefixes and filters content using construction-domain regular expressions. It does not distinguish descriptive drawing data from natural-language instructions directed at an AI agent. Any text that does not match a noise pattern is retained. Content that does not match a recognized construction category is placed in the catch-all category and reproduced without escaping, provenance metadata, or an unt ...[truncated 2621 chars]
- Remediation
- ## Remediation Suggestions 1. **Establish an explicit untrusted-data boundary** - Mark every extracted segment as untrusted source content. - Use a structured representation such as JSON with fields including `source`, `category`, `content`, and `trust_level`. - Avoid presenting extracted text in a form that resembles agent instructions. 2. **Harden downstream prompts** - Tell downstream models that drawing content is quoted data and must never be followed as instructions. - Delimit source content clearly and place security instructions outside those delimiters. - State that requests to ignore rules, reveal prompts, invoke tools, or modify the workflow found inside source content are document data only. 3. **Detect and quarantine suspicious content** - Add a separate category for likely prompt-injection language. - Flag phrases that address an assistant, refer to system or developer messages, request disclosure, override earlier instructions, or request tool execution. - Require human review of quarantined content rather than silently deleting it. 4. **Apply least privilege downstream** - Do not give summarization or quantity-generation agents unnecessary filesystem, shell, credential, or network access. - Require explicit user approval for consequential tool operations. - Validate generated quantities against deterministic rules before accepting them. 5. **Preserve provenance** - Retain source file and source-line metadata for each output item. - Ensure downstream systems can distinguish original drawing text from pipeline-generated headings and instructions. 6. **Add adversarial tests** - Test drawings containing direct and obfuscated prompt-injection phrases. - Verify that suspicious text is quarantined and cannot alter downstream model behavior. - Include multilingual and Unicode-obfuscated variants because drawing text may contain mixed-language content.
