Back to skill

Security audit

Arxiv Skill Extractor

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent research-to-skill purpose, but it can persistently create or overwrite agent-loadable skills using untrusted paper metadata.

Review pending_skill_task.json and paper metadata before running this skill, and avoid installing or loading generated skills until their SKILL.md content has been checked for prompt-injection text. Use it only in a workspace where overwriting generated arXiv skill directories would not destroy important work.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

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. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:103
Finding
Title-derived directory collisions can overwrite existing skills<![CDATA[ ## Vulnerability Details **File Location**: `index.js:103-117` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Medium ### Vulnerable Code ```javascript // 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 })); fs.writeFileSync(path.join(scriptsDir, "run.js"), renderNodeRunner({ paper })); fs.writeFileSync(path.join(skillDir, "paper.json"), `${JSON.stringify(paper, null, 2)}\n`); ``` ### Technical Analysis For normalized titles of five or more characters, the output directory name contains only the first 40 characters of the sanitized title. The paper key is not included. Different papers can therefore resolve to the same directory when they: - Have identical titles. - Differ only in characters removed or normalized by `sanitizeSlug()`. - Share the same first 40 normalized characters. - Are intentionally assigned a title crafted to match an existing generated skill. The code calls `ensureDir()` and then uses `fs.writeFileSync()` without exclusive-create flags, identity verification, or collision detection. Existing `SKILL.md`, `scripts/run.js`, and `paper.json` files at the resolved path are consequently overwritten. ### Attack Path 1. An existing skill is stored under a predictable path such as `skills/arxiv-example-title`. 2. An attacker supplies paper metadata whose normalized title resolves to the same `skillName`. 3. `ex ...[truncated 1235 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Always include a stable unique identifier in the directory name, such as a validated paper key or a cryptographic digest: ```javascript const uniqueSuffix = crypto .createHash("sha256") .update(finalPaperKey) .digest("hex") .slice(0, 12); const skillName = `arxiv-${titleSlug || "paper"}-${uniqueSuffix}`; ``` 2. Refuse to overwrite existing directories by default. Create the target directory or files with exclusive semantics and report a collision to the caller. 3. Store a manifest containing the canonical paper key and verify it before updating an existing generated skill. 4. Require an explicit, authenticated overwrite option for intentional regeneration. 5. Write generated files to a new temporary directory and atomically rename it only after validation, while ensuring the destination does not already exist. 6. Add tests for identical titles, normalization collisions, truncation collisions, and attempts to overwrite pre-existing skill directories. 7. Consider preserving backups or using versioned output directories when regeneration is an expected operation. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Missing User Warnings

Low
Confidence
79% confidence
Finding
For markdown files, warnings should disclose behaviors that may affect user data, privacy, or system integrity. The automation section states that the skill automatically reads `pending_skill_task.json` and runs the extraction loop, but does not warn users about local file consumption or automated processing side effects.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
Natural-language policy issues include forcing a specific language or locale without user opt-in. In this file, the automation instructions include Chinese comments (`自动读取...`, `或直接指定...`) embedded in otherwise English documentation, which can impose a language expectation on users without explanation.

Static analysis

No suspicious patterns detected.