T09 · Insecure Skill Coding Practices
- Location
scripts/clean_drawing.py:208- Finding
Untrusted Drawing Text Is Forwarded Verbatim to Downstream AI Systems
- Content
View full analysis
Vulnerability Details
File Location:
scripts/clean_drawing.py:208-220, 266; related downstream workflow inSKILL.md:87, 101
Vulnerability Type: Indirect prompt-injection exposure through insufficient output sanitization
Risk Level: MediumVulnerable 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 skillSKILL.md:101also recommends sending content from the catch-all category to a language model for summarization before passing it toboq-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
View remediation
Remediation Suggestions
-
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, andtrust_level. - Avoid presenting extracted text in a form that resembles agent instructions.
-
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.
-
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.
-
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.
-
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.
-
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.
-
