Back to skill

Security audit

skill-router

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it tries to become a global router for every request and can expose or persist information from locally installed skills.

Install only if you are comfortable with a skill that tries to route every question and report skill usage every time. Review generated indexes before use, avoid scanning private or untrusted skills, and do not share generated router files if they reveal sensitive installed capabilities.

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
SKILL.md:3
Finding

Global Agent Instruction and Response-Format Hijacking

Content
View full analysis
**Core Directive**: Before answering any user question, you MUST consult this skill first, check for matching specialized skills, and load them if found. ``` ```markdown ### Rule 1: Match & Load When the user's question matches any skill above, load it using the `Skill` tool. Load all matching skills — don't skip any. ### Rule 2: Combined Loading Common combos: - **Code + Standards** → Language-specific skill + `coding-standards` - **Deploy** → `deployment-patterns` + `canary-watch` - **API Design** → `api-design` + `backend-patterns` - **Frontend** → `frontend-design` + `frontend-patterns` - **Writing** → `article-writing` + `brand-voice` - **Tech Decision** → `blueprint` + `architecture-decision-records` - **Code Walkthrough** → `code-tour` + `codebase-onboarding` General matching rules: - When the user's question contains domain keywords, tech stack names, or terminology, load the matching skill - One question may match multiple skills — load them all - When in doubt, load one more rather than one less ``` ```markdown ## 3. Usage Report (Mandatory) **After every task, you MUST report which skills were actually used at the end of your response.** --- **Skill Usage Report:** - [skill-name] — [Status: Loaded / Not Triggered — Notes] - List all matched skills with load status - Also report when no skills were triggered - **This report MUST appear at the end of every response, never omit it.* ...[truncated 1965 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate.py:62
Finding

Persistent Markdown Instruction Injection Through Unescaped Skill Metadata

Content
View full analysis
dict | None: """Extract name and description from SKILL.md frontmatter / 从 SKILL.md 提取 name 和 description""" try: content = path.read_text(encoding="utf-8") except Exception: return None # Match YAML frontmatter / 匹配 YAML frontmatter fm_match = re.match(r"^---\s*\n(.*?)\n---", content, re.DOTALL) if not fm_match: return None fm = fm_match.group(1) name = re.search(r"^name:\s*['\"]?(.+?)['\"]?\s*$", fm, re.MULTILINE) desc = re.search(r"^description:\s*['\"]?(.+?)['\"]?\s*$", fm, re.MULTILINE) if not name: return None return { "name": name.group(1).strip().strip('"').strip("'"), "description": desc.group(1).strip().strip('"').strip("'") if desc else "", "path": str(path.parent), } ``` ```python def generate_index(categories: dict[str, list[dict]]) -> str: """Generate skill index table in Markdown / 生成技能索引 Markdown 表格""" lines = [] # Preserve category order / 按自定义顺序排列类别 category_order = list(CATEGORY_RULES.keys()) + ["Other / 其他"] for cat in category_order: if cat not in categories: continue skills = categories[cat] lines.append(f"### {cat}") lines.append("| Skill / 技能 | Trigger / 触发场景 |") lines.append("|--------|----------|") for s in sorted(skills, key=lambda x: x["name"]): # Use first sentence of description as trigger summary # 取 description 的第一句作为触发场景摘要 desc = s["description"] trigger = desc.split(".")[0].strip() if len(trigger) > 80: trigger = trigger[:77] + "..." lines.append(f"| `{s['name']}` | {trigger} |") ...[truncated 3497 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose says this skill is a runtime router to be consulted for every user query, but the embedded notes indicate the surrounding implementation generates documentation/index content offline and scans local files. This mismatch can mislead operators and downstream agents about what the skill actually does, reducing oversight and potentially enabling broader filesystem access or unintended automation under an innocuous description.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The description says the skill should be consulted first for any question and 'never' skipped, creating near-universal activation. A universally-triggered router can dominate execution flow, force unnecessary skill loading, and widen the attack surface by causing other skills to be invoked even when not needed.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The core directive mandates consulting this skill before answering any user question, which creates ambiguous universal activation and can override more specific safety or task-routing logic. In practice, this can produce priority inversion, unnecessary dependency loading, and a persistent control point that amplifies mistakes or malicious modifications in the router.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README instructs users to run a generator that scans the local ~/.claude/skills directory and reads each SKILL.md, but it does not warn that this enumerates locally installed skills and processes their metadata. That can expose sensitive information about a user's tooling, specialty areas, internal skills, or security-related capabilities if the generated index is shared, committed, or surfaced in model outputs.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README.md (reported line 44)May include surrounding context.

bash
# Linux / macOS
cp SKILL.md ~/.claude/skills/skill-router/SKILL.md

# Windows
xcopy SKILL.md "%USERPROFILE%\.claude\skills\skill-router\SKILL.md*" /Y

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README_CN.md (reported line 45)May include surrounding context.

bash
# Linux / macOS
cp SKILL.md ~/.claude/skills/skill-router/SKILL.md

# Windows
xcopy SKILL.md "%USERPROFILE%\.claude\skills\skill-router\SKILL.md*" /Y

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instruction to "ask any question" implies the skill may activate on essentially arbitrary user input, which overlaps with everyday speech and does not define clear activation boundaries. The README does not provide specific trigger conditions, constraints, or negative examples to clarify when the router should or should not engage.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README.md (reported line 124)May include surrounding context.

Custom skills directory

bash
python scripts/generate.py --skills-dir /path/to/your/.claude/skills

Custom output path

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README_CN.md (reported line 125)May include surrounding context.

Custom skills directory

bash
python scripts/generate.py --skills-dir /path/to/your/.claude/skills

Custom output path

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly positions the router as something Claude should consult for essentially every user question, without meaningful trigger boundaries. In a skill system, that creates overbroad activation and can cause unnecessary loading of unrelated skills, expanding the attack surface and increasing the chance that sensitive context or user prompts are routed into the wrong skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Allowing manual indexes in arbitrary formats with unconstrained trigger phrases and claiming the model can understand anything leaves routing semantics undefined. That ambiguity makes it easier to smuggle in overbroad, conflicting, or prompt-like trigger text that can manipulate model behavior and cause inappropriate skill activation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The keyword-based matching guidance is overly broad ('domain keywords', 'tech stack names', 'when in doubt, load one more'), which encourages over-triggering and loading multiple skills without strong relevance checks. This increases prompt-injection exposure from additional skill content and raises the chance of irrelevant or conflicting instructions affecting responses.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · scripts/generate.py (reported line 24)May include surrounding context.

python
from collections import defaultdict

# === Config / 配置 ===
DEFAULT_SKILLS_DIR = os.path.expanduser("~/.claude/skills")
DEFAULT_OUTPUT = "SKILL.md"

# === Auto-categorization Rules / 自动分类规则 ===

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

Mandating a usage report at the end of every answer can leak internal capability inventory and decision logic without user opt-in. In this skill's context, the report may disclose which specialized skills are installed, triggered, or considered, which is useful reconnaissance for prompt injection, policy evasion, or environment fingerprinting.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The README is predominantly in Chinese and does not state that language choice is optional or user-selectable. Under the language/locale policy, forcing a specific language without opt-in can be a natural-language policy issue unless clearly documented as region-specific or optional.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring, usage instructions, and later CLI messages consistently present Chinese alongside English, indicating a fixed locale/output policy. The file does not offer any language selection flag or documented opt-in, which conflicts with the rule against forcing a specific language or locale without user choice.

Content

No source excerpt is available for this finding.