T01 · Skill Instruction Hijacking
Error
- Location
- index.js:15
- Finding
- Untrusted paper metadata is embedded into generated skill instructions<![CDATA[ ## Vulnerability Details **File Location**: `index.js:15-42`, with untrusted input acquisition and file generation at `index.js:98-117` **Vulnerability Type**: T01: Skill Instruction Hijacking **Risk Level**: High ### Vulnerable Code ```javascript function renderSkillMarkdown({ skillName, paper }) { const title = String(paper.title || "Untitled Paper"); const categories = String(paper.categories || "research"); const paperKey = String(paper.paper_key || "unknown-paper-key"); const abstract = String(paper.abstract || "").trim(); const abstractSnippet = abstract ? abstract.slice(0, 500) : "No abstract provided."; const description = `Learned from arXiv paper ${title}. Use this skill to scaffold Node.js experiments based on the paper method.`; return `--- name: ${skillName} description: ${JSON.stringify(description)} metadata: '{"openclaw":{"requires":{"bins":["node"]}}}' --- # ${skillName} ## Source - Paper key: ${paperKey} - Title: ${title} - Categories: ${categories} ## Learned insight ${abstractSnippet} ## Node.js implementation entry \`node {baseDir}/scripts/run.js\` `; } ``` The generated content is sourced and written as follows: ```javascript const paper = options.paper || (await getPaper(finalPaperKey)); // Use title for readable slug, fallback to paper key if title missing const titleSlug = sanitizeSlug(paper.title || "").slice(0, 40); const keySlug = sanitizeSlug(paper.paper_key || finalPaperKey).slice(0, 8); // Naming convention: arxiv-<title-slug> // If title is too short or missing, append key for uniqueness let skillName = `arxiv-${titleSlug}`; if (titleSlug.length < 5) { skillName = `arxiv-learned-${keySlug}`; } const skillDir = path.join(WORKSPACE_ROOT, "skills", skillName); const scriptsDir = path.join(skillDir, "scripts"); ensureDir(scriptsDir); fs.writeFileSync(path.join(skillDir, "SKILL.md"), renderSkillMarkdown({ skillName, paper })); ``` ### Technical Analysis The paper title, categories, paper key, an ...[truncated 2134 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all paper metadata as untrusted data rather than skill instructions. 2. Prefer storing the original title, abstract, categories, and paper key only in `paper.json`. Keep `SKILL.md` limited to fixed, developer-controlled instructions. 3. If metadata must appear in `SKILL.md`, serialize it into a strictly delimited data block and escape Markdown metacharacters, frontmatter delimiters, HTML, and line breaks that can alter document structure. 4. Add fixed instructions stating that content inside the paper-data block is quoted source material and must never be followed as instructions. 5. Validate generated skill documents before writing or installing them. Reject metadata containing frontmatter delimiters, unexpected headings, instruction-like control text, or unsupported characters where appropriate. 6. Preserve provenance for the source of each paper record and require trusted-source validation before generating an Agent-loadable skill. 7. Add tests using adversarial values such as Markdown headings, frontmatter delimiters, tool-use requests, and prompt-override language to confirm that they remain inert data. ]]>
