T01 · Skill Instruction Hijacking
Warning
- Location
- scripts/generate-skill.sh:73
- Finding
- Generated Skill fields permit persistent instruction and YAML injection## Vulnerability Details **File Location**: `scripts/generate-skill.sh:73-74, 98, 148-153` **Vulnerability Type**: Persistent instruction injection through insufficient input validation **Risk Level**: Medium ### Vulnerable Code ```bash # Check high-risk fields for prompt injection check_prompt_injection "description" "$DESCRIPTION" check_prompt_injection "instructions" "$INSTRUCTIONS" ``` ```bash # Sanitize skill name: lowercase, hyphens only SLUG=$(printf '%s' "$NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//') ``` ```bash # Write SKILL.md using printf to avoid echo expansion issues { printf '%s\n' "---" printf 'name: %s\n' "$SLUG" printf 'description: %s\n' "$DESCRIPTION" if [ -n "$METADATA" ]; then printf '%s\n' "$METADATA" fi printf '%s\n' "---" printf '\n' printf '# %s\n' "$NAME" printf '\n' printf '%s\n' "$INSTRUCTIONS" } > "$SKILL_DIR/SKILL.md" ``` ### Technical Analysis The generator applies a finite prompt-injection phrase denylist only to `DESCRIPTION` and `INSTRUCTIONS`. The original `NAME` value is not passed to `check_prompt_injection()`, even though it is written into the generated document body. The validation also allows carriage returns and newlines in the name, description, and instructions. In particular, `DESCRIPTION` is inserted directly into YAML frontmatter without YAML quoting, escaping, or scalar serialization. A multiline description can therefore introduce arbitrary YAML fields or a `---` delimiter that prematurely terminates the frontmatter. Subsequent lines then become prompt-loaded Markdown instructions. The phrase denylist does not provide structural protection and can be bypassed using instructions that avoid the enumerated wording. The generated file may consequently contain persistent behavioral instructions even though the project presents the filtering as a security boundary. ...[truncated 1328 chars]
- Remediation
- ## Remediation Suggestions 1. Reject carriage returns, line feeds, NUL bytes, and YAML document delimiters in all frontmatter scalar inputs. 2. Validate `NAME` separately and use only the validated slug in both frontmatter and headings. 3. Pass every prompt-loaded input field, including `NAME`, through the same content-security policy. 4. Serialize frontmatter with a trusted YAML implementation rather than constructing it with `printf`. 5. Prefer an allowlist of permitted single-line characters for names and descriptions. 6. Treat phrase matching only as defense in depth, not as the primary injection boundary. 7. Parse the completed file and confirm that it contains exactly one frontmatter block with the expected fields. 8. Require explicit operator approval of the exact generated file before installation or activation. 9. Extend `validate.sh` to reject duplicate delimiters, unexpected frontmatter fields, multiline scalar injection, and malformed YAML.
