T09 · Insecure Skill Coding Practices
- Location
SKILL.md:38- Finding
Unsanitized Skill Metadata Is Injected into the Agent Prompt
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 38-42
Vulnerability Type: Prompt injection through untrusted skill metadata
Risk Level: MediumVulnerable Code
javascript if (topSkills.length > 0) { return { prompt: `\n\n## Skill Hint\nFocus on: ${topSkills.map(s => s.skill.name).join(", ")}\n` }; }Technical Analysis
Skill names returned by
getAllSkills()are interpolated directly into an instruction-bearing prompt. The code applies no validation, escaping, length restriction, or removal of control characters before usings.skill.name.If an attacker can register or install a skill with crafted metadata, its name can contain line breaks and instruction-like content that escapes the intended comma-separated list. The generated text may then be interpreted by the agent as additional trusted instructions rather than inert metadata.
The score is based on the skill description, so an attacker can also choose a description containing likely task keywords to increase the chance that the malicious skill reaches
topSkills. This is an insecure prompt-construction pattern; the audited file does not establish that the project itself intentionally contains a malicious skill.Attack Path
- An attacker obtains the ability to make a skill visible to
getAllSkills(), such as by convincing a user or administrator to install an attacker-controlled skill. - The attacker gives the skill a description containing keywords associated with targeted user requests.
- The attacker crafts the skill name with newline-delimited instructions, for example a benign-looking name followed by text intended to redirect agent behavior.
- A user submits a message whose extracted keywords overlap with the malicious description.
- The scoring logic ranks the malicious skill above the configured threshold and includes it in
topSkills. - The hook inserts the crafted name into the
Skill Hintprompt without sanitization. - The age ...[truncated 684 chars]
- An attacker obtains the ability to make a skill visible to
- Remediation
View remediation
Remediation Suggestions
- Treat every value returned by
getAllSkills()as untrusted input. - Enforce a strict skill-name allowlist, such as
^[A-Za-z0-9._-]{1,64}$. - Reject line breaks, control characters, prompt delimiters, markup, and other characters capable of changing the generated prompt structure.
- Avoid interpolating metadata into instruction-bearing prompt text. Supply matched skills through a structured data channel with explicit schema validation where supported.
- If textual prompt inclusion is unavoidable, serialize names using a safe encoding and clearly delimit them as untrusted data.
- Validate and constrain descriptions as well as names, because descriptions control ranking and can be manipulated to target common user requests.
- Apply trust or provenance checks before including installed skills in automatic matching.
- Add security tests covering malicious names, embedded newlines, instruction-like strings, oversized metadata, Unicode control characters, and keyword-stuffed descriptions.
- Treat every value returned by
