T02 · Agent Memory Poisoning
Error
- Location
- SKILL.md:51
- Finding
- Persistent Agent Instruction Injection Through Generated Configuration<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:51-109`, `SKILL.md:156-169`, `SKILL.md:200-209`, and `SKILL.md:400-405` **Vulnerability Type**: Persistent instruction and configuration injection **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### 1.2 User profile 1. **Role** -- what they do. Goes into CLAUDE.md `[ROLE]`. Example: "a backend developer", "a full-stack engineer" 1. **Experience level** -- "experienced" or "learning while developing". Goes into CLAUDE.md `[LEVEL]`. 1. **Preferred language** -- for AI conversations and documentation. Goes into CLAUDE.md `[YOUR_LANGUAGE]`. Example: "English", "简体中文", "日本語" ``` ```markdown ### 2.3 Customize CLAUDE.md Read the template CLAUDE.md and replace all placeholders. For the complete mapping of placeholders to collected values, read `references/claude-md-fields.md`. Key replacements: - `[ROLE: e.g., ...]` -> collected role - `[LEVEL: e.g., ...]` -> collected level - `[YOUR_LANGUAGE: e.g., ...]` -> collected language (appears twice) - `[YOUR_FORMAT_COMMAND]` -> confirmed formatter - `[YOUR_LINT_COMMAND]` -> confirmed linter - `[YOUR_TYPE_CHECK_COMMAND]` -> confirmed type checker - `[YOUR_TEST_COMMAND]` -> confirmed test runner - `[PROJECT_STYLE_GUIDE: e.g., ...]` -> style guide based on tech stack - Repository table in section 1 -> generated from repo list ``` ```markdown ### 3.2 Generate config.yaml Read `references/config-template.yaml` and populate it with: - `{project_name}` -> collected project name - `{description}` -> collected description - `{repos_list}` -> formatted repo list, one per line: ```text - **{name}**: {description} ``` Write the result to `openspec/config.yaml`. ``` ```markdown **CLAUDE.md** (partially customized): - Fetch the new template version - Extract the user's current filled values (role, level, language, commands, repo table) - Apply the new template structure - Re-fill the extracted values into the new template - Show the us ...[truncated 2544 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Define strict schemas for every collected value: - Restrict project and repository names to safe identifiers. - Require role, language, and descriptions to be single-line values. - Enforce reasonable length limits. - Reject control characters and unexpected Markdown headings, code fences, or instruction-like blocks. 2. Do not place untrusted user content directly into Agent instruction sections. Store user metadata in a separate structured data file and reference it as data. 3. Allow only predefined development commands, or construct commands from an allowlist of executable names and fixed arguments. 4. Generate YAML with a maintained YAML serialization library rather than textual placeholder replacement. 5. Escape Markdown table delimiters, line breaks, backticks, and other structural characters before generating `CLAUDE.md`. 6. Show the complete generated diff and require explicit confirmation before writing instruction-bearing files. 7. During update mode, validate previously stored values again before reinserting them. Do not assume existing workspace content is trusted. 8. Mark generated data boundaries clearly so that future Agents can distinguish user-supplied metadata from authoritative instructions. ]]>
