Back to skill

Security audit

Skill Router

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible router, but it includes broad fallback and orchestration instructions that can lead to shell commands, external API calls, email sending, and prompt-injection exposure without tight scoping or confirmation.

Install only if you are comfortable reviewing and constraining the fallback catalog yourself. Do not allow automatic execution of its exec templates, email steps, package installs, or external API calls without explicit confirmation and proper input escaping.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
tool_catalog.json:58
Finding
Shell Command Injection in L0 Fallback Invocation Templates<![CDATA[ ## Vulnerability Details **File Location**: `tool_catalog.json:58-64` **Vulnerability Type**: User-controlled input embedded in shell command templates **Risk Level**: High ### Vulnerable Code ```json { "name": "PubMed E-utilities", "priority": 1, "invocation": "exec: curl -s 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmax=20&api_key=${NCBI_API_KEY}&term=QUERY' | Then use efetch to obtain details", "strength": "Biomedical literature gold standard with complete metadata", "limitation": "Biomedical content only; no AI summary", "free": true, "notes": "API key is available in the NCBI_API_KEY environment variable" } ``` Equivalent unsafe placeholders occur in other catalog commands, including `QUERY`, `URL`, `RECIPIENT`, `SUBJECT`, `BODY`, `OUTPUT`, and `PMID`. ### Technical Analysis The catalog explicitly labels the command as an `exec` invocation and places the `QUERY` placeholder inside a shell command string. It does not define URL encoding, shell escaping, argument validation, or an argument-array execution contract. If an external catalog runner performs direct string replacement and passes the resulting command to a shell, a query containing a single quote and shell metacharacters can terminate the quoted URL and append another command. Similar issues affect email fields, download URLs, output paths, and JSON bodies elsewhere in the catalog. The project does not contain the catalog executor, so the vulnerable operation depends on the surrounding Agent framework interpreting the documented `exec:` template. Nevertheless, the template instructs the framework to construct an unsafe shell command from user-controlled data. ### Attack Path 1. An attacker submits a query containing shell syntax designed to terminate the single-quoted URL. 2. The router rejects the request at the L1 Skill-routing layer and sends it to the L0 fallback layer. 3. The fallback implementation selects the PubMed or another `ex ...[truncated 947 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace shell-form command templates with structured invocation definitions: ```json { "method": "GET", "url": "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi", "query_parameters": { "db": "pubmed", "retmax": 20, "api_key_env": "NCBI_API_KEY", "term_input": "QUERY" } } ``` 2. Use a native HTTP client or a structured tool API rather than `curl`. 3. If a subprocess is unavoidable, call it with an argument array and `shell=False`. 4. Apply URL encoding and JSON serialization through standard libraries rather than string concatenation. 5. Validate PMIDs, email recipients, URLs, and output paths against strict schemas. 6. Restrict network destinations to an explicit allowlist. 7. Never expose expanded commands containing API keys in logs or model context. 8. Require user confirmation before transmitting potentially sensitive medical or personal queries. ]]>

T01 · Skill Instruction Hijacking

Error
Location
router_top5.py:476
Finding
Untrusted Indexed Skill Instructions Are Injected into the LLM Selection Prompt<![CDATA[ ## Vulnerability Details **File Location**: `router_top5.py:476-479`; `schemas.py:28-40` **Vulnerability Type**: Indirect prompt injection through indexed third-party Skill content **Risk Level**: High ### Vulnerable Code ```python profile = SkillProfile( name=r["name"], description=r.get("description", ""), dir=r.get("dir", ""), path=r.get("path", ""), capabilities=r.get("capabilities", []), brief_guide=r.get("brief_guide", ""), body_start=r.get("body_start", ""), relevance=r.get("relevance", 0.0), ) blocks.append(profile.to_prompt_block(i + 1)) ``` The selected `body_start` value is serialized directly into the LLM prompt: ```python def to_prompt_block(self, index: int) -> str: """Format as a text block for the LLM.""" lines = [ f"{index}. {self.name} (relevance: {self.relevance:.2f})", f" Description: {self.description}", ] if self.capabilities: lines.append(f" Capabilities: {', '.join(self.capabilities)}") if self.brief_guide: lines.append(f" Guide: {self.brief_guide}") if self.body_start: lines.append(f" Details: {self.body_start}") lines.append(f" Path: {self.path}") return "\n".join(lines) ``` ### Technical Analysis The router reads `body_start` and `brief_guide` from `skill_index.json`, which aggregates instructional text from many third-party Skills. These fields are inserted verbatim into a prompt described as being sent directly to the LLM. The index contains imperative operational material, including package installation, API calls, cron setup, and instructions telling an Agent how it should act. The serialization format does not: - Mark indexed text as untrusted data. - Escape or normalize instruction-like content. - Separate candidate metadata from executable Skill instructions. - Restrict the LLM to a structured selection response. - Verify a selected Skill in a separate trust boundary. Consequently, a malicious or c ...[truncated 1552 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `body_start` from the first-stage candidate-selection prompt. 2. Route using normalized metadata only, such as an immutable identifier, trusted description, capability IDs, and numeric relevance. 3. Require the LLM to return a schema-validated list of candidate IDs rather than free-form instructions. 4. Treat all indexed Skill text as untrusted content and clearly delimit it as quoted data. 5. Reject candidate metadata containing instruction-hijacking phrases, role markers, tool-call directives, or hidden markup. 6. Maintain a signed or administrator-approved Skill index. 7. After selection, perform a separate security and permission review before loading the full Skill instructions. 8. Enforce least privilege so selection alone cannot grant shell, network, filesystem, email, or credential access. ]]>

T08 · Insecure Dependencies

Warning
Location
router_top5.py:22
Finding
Unpinned Embedding Model Downloaded from a Third-Party Mirror<![CDATA[ ## Vulnerability Details **File Location**: `router_top5.py:22-24` **Vulnerability Type**: Unverified remote dependency retrieval **Risk Level**: Medium ### Vulnerable Code ```python import os os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" from sentence_transformers import SentenceTransformer _EMBEDDING_MODEL = SentenceTransformer("all-MiniLM-L6-v2") ``` ### Technical Analysis The router globally redirects Hugging Face model retrieval to `https://hf-mirror.com` and loads the model using only the mutable name `all-MiniLM-L6-v2`. No immutable revision, checksum, signature, or local artifact verification is specified. On a first run or cache miss, `SentenceTransformer` may retrieve model and configuration artifacts from the configured mirror. The effective dependency can therefore change after the Skill has been reviewed. A compromised mirror, altered upstream artifact, or dependency-resolution change could supply manipulated content. The documentation discloses that the initial model download requires network access, but the use of a noncanonical mirror and lack of integrity pinning exceed the minimum trust required for an otherwise local router. ### Attack Path 1. The embedding model is absent from the local cache. 2. The router sets `HF_ENDPOINT` to the third-party mirror. 3. `SentenceTransformer` resolves the mutable model identifier through that mirror. 4. A compromised or altered artifact is downloaded without an application-level integrity check. 5. The runtime loads the artifact or uses its configuration. 6. The altered dependency affects routing behavior or exploits a vulnerability in the model-loading stack. ### Impact Assessment Likely impacts include: - Manipulation of embedding results and Skill selection. - Denial of service through malformed or oversized artifacts. - Exposure to vulnerabilities in model deserialization or dependency loading. - Potential code execution if a vulnerable loader processes a malicious artifact. - ...[truncated 211 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use the canonical trusted model registry unless a mirror has been formally approved. 2. Pin an immutable model revision or commit identifier. 3. Verify every downloaded file against maintained SHA-256 checksums or signatures. 4. Package a prevalidated offline model artifact where deployment size permits. 5. Disable implicit remote retrieval in production and fail closed when the verified model is unavailable. 6. Pin `sentence-transformers`, its transitive dependencies, and the supported serialization format in a lockfile. 7. Avoid globally modifying `HF_ENDPOINT`; pass a scoped, explicit download configuration instead. ]]>

T08 · Insecure Dependencies

Warning
Location
tool_catalog.json:19
Finding
Unpinned Global npm Package Installation in AI Fallback Setup<![CDATA[ ## Vulnerability Details **File Location**: `tool_catalog.json:19-23` **Vulnerability Type**: Unpinned global dependency installation with lifecycle-code execution **Risk Level**: Medium ### Vulnerable Code ```json { "name": "9Router Free AI", "priority": 1, "invocation": "curl -s http://localhost:20128/v1/chat/completions -H 'Content-Type: application/json' -d '{\"model\":\"kr/claude-sonnet-4.5\",\"messages\":[{\"role\":\"user\",\"content\":\"QUERY\"}]}' | jq -r '.choices[0].message.content'", "strength": "Free AI model fallback with automatic failover across more than 40 providers", "limitation": "Requires a locally running 9Router instance (npm install -g 9router; 9router)", "free": true, "setup": "npm install -g 9router && 9router # Start backend on port 20128" } ``` ### Technical Analysis The setup instructs users or an Agent to install the latest available `9router` package globally. It does not pin a version, lock transitive dependencies, verify package integrity, or isolate the installation. npm installation can execute package lifecycle scripts such as `preinstall`, `install`, and `postinstall`. A compromised package release, account takeover, dependency confusion event, or malicious transitive dependency could therefore execute code during setup. Global installation also writes outside the project environment and may affect other sessions and users. This installation is not necessary for the core local routing function; it is an optional fallback and therefore exceeds the minimum dependency and filesystem privileges required by the declared router. ### Attack Path 1. The local AI fallback service is unavailable. 2. A user or automated Agent follows the catalog's setup instruction. 3. npm resolves the latest mutable release of `9router` and its dependencies. 4. npm executes package lifecycle scripts during global installation. 5. A compromised package or transitive dependency executes code with the installing user's priv ...[truncated 693 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not automatically install global packages from Skill instructions. 2. Pin an audited package version and expected registry. 3. Use a lockfile and verify npm integrity metadata. 4. Install into a project-local, containerized, or otherwise isolated environment. 5. Disable lifecycle scripts during inspection and explicitly audit any scripts required at deployment. 6. Require informed user approval before installation or service startup. 7. Bind the service strictly to loopback, authenticate local requests, and limit accepted request sizes. 8. Prefer the direct built-in fallback when the optional service has not already been installed securely. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (64)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
If the claimed embedding, translation, reranking, and rejection mechanisms are absent, the skill may handle ambiguous or information-only queries without the promised safeguards. In a router, missing guardrails are security-relevant because they directly affect whether sensitive prompts, external-tool invocations, or inappropriate LLM context exposure are prevented.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the claimed embedding, translation, reranking, and rejection mechanisms are absent, the skill may handle ambiguous or information-only queries without the promised safeguards. In a router, missing guardrails are security-relevant because they directly affect whether sensitive prompts, external-tool invocations, or inappropriate LLM context exposure are prevented.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the claimed embedding, translation, reranking, and rejection mechanisms are absent, the skill may handle ambiguous or information-only queries without the promised safeguards. In a router, missing guardrails are security-relevant because they directly affect whether sensitive prompts, external-tool invocations, or inappropriate LLM context exposure are prevented.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the claimed embedding, translation, reranking, and rejection mechanisms are absent, the skill may handle ambiguous or information-only queries without the promised safeguards. In a router, missing guardrails are security-relevant because they directly affect whether sensitive prompts, external-tool invocations, or inappropriate LLM context exposure are prevented.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The manifest describes a sophisticated router that does embedding coarse filtering, LLM reranking, Chinese-to-English query translation, and triple rejection logic. In contrast, match_chain() only lowercases the query and scores chains by trigger_caps, substring keyword matches, and step capability overlap from local JSON data, with no embedding, no LLM call, no translation, and no rejection pipeline.

Vague Triggers

High
Confidence
99% confidence
Finding
The action-phrase exemption list contains ambiguous, high-frequency phrases like '给我', '把', '查一下', and '列出来', and applies them based on query prefix. Because these phrases are generic instruction openers, an attacker or ordinary user can easily craft unrelated text that bypasses the rejection layer and gets treated as actionable skill intent, undermining the router's safety boundary.

Vague Triggers

High
Confidence
98% confidence
Finding
The `using-superpowers` rule mandates skill invocation whenever there is even a 1% chance a skill might apply, which is effectively an always-on trigger. In a skill ecosystem containing many powerful and instruction-bearing entries, this creates a strong prompt-injection and over-activation risk by forcing the agent to consult more potentially adversarial content than necessary.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The fallback catalog exposes powerful side-effecting capabilities—email sending, browser automation, file downloads, local script execution, and remote API access—inside a skill whose stated purpose is routing/selection rather than execution. This creates dangerous scope expansion: if the router or downstream policy misfires, an attacker can pivot from benign query routing into outbound actions, data exfiltration, or code execution that users would not reasonably expect from a routing layer.

Missing User Warnings

High
Confidence
98% confidence
Finding
The email capability can send real outbound messages from a configured sender account, but the catalog does not prominently warn about this side effect or require confirmation. In a fallback path, this is especially dangerous because a low-confidence routing failure could unexpectedly trigger external communication, spam, phishing, or sensitive data leakage.

Lp3

Medium
Category
MCP Least Privilege
Confidence
79% confidence
Finding
The skill advertises capabilities that involve local resources and environment-injected API keys, but it does not declare an explicit tool/permission scope. That creates an authorization ambiguity: a host may grant broader file or environment access than reviewers and users expect, increasing the chance of unintended secret exposure or local file access.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Forcing Chinese queries to be translated into English without user choice can alter meaning and may send sensitive content through additional processing stages, increasing privacy and integrity risk. In a routing skill, translation errors can also cause incorrect tool selection, especially for medical, legal, or safety-sensitive requests where nuance matters.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring and surrounding instructional text are written entirely in Chinese, and the taxonomy design explicitly centers Chinese query handling alongside English rather than offering a user language choice. This can violate a language/locale policy when a skill imposes a specific language experience without documented opt-in or justification.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest describes a routing engine that selects among skills after embedding and LLM ranking, with rejection of purely informational queries. In this file, the router taxonomy explicitly classifies actionable capabilities such as sending email, task management, and system operations, which goes beyond a narrowly described information-routing function and embeds orchestration over sensitive operational domains.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The ChainStep documentation states input_mapping values may be "query", but format_plan() checks only for source == "$query" before rendering it as the user's original query. This is an active contradiction between the documented mapping convention and the implemented handling.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The manifest presents the skill as a routing engine for picking top 5 skills, but this file formats execution plans and generates per-step execution context for multi-step chains. That is broader than ranking skills and indicates orchestration support rather than just routing.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The router manifest includes an email-sending step in the paper_writing chain, which creates an external side effect unrelated to the stated purpose of selecting or routing skills. If invoked automatically or implicitly, it can transmit generated content and references to an email destination without clear user intent, expanding the attack surface from routing into data exfiltration or unintended outbound actions.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The email-sending step lacks any indication of user-facing warning, disclosure, or consent flow before outbound transmission. Without a clear notice that content will leave the system, users may unknowingly cause sensitive draft material or references to be sent externally.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The search_and_email workflow summarizes literature and emails the result without any documented warning that content will be transmitted externally. This lack of transparency increases the risk of inadvertent disclosure and violates the principle of explicit user consent for side-effectful actions.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The search_and_email chain directly sends summarized content by email, which exceeds the declared scope of a routing engine and introduces an unnecessary exfiltration pathway. In a router context, users may expect skill selection assistance, not automatic delivery of content to external recipients, making unintended disclosure more likely.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The daily_research chain uses broad trigger keywords such as general references to daily research updates, which can overlap with ordinary conversation. In combination with downstream email behavior, loose activation conditions increase the chance that a benign query unintentionally launches a workflow with external side effects.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The daily research sync chain performs automatic email notification without any explicit disclosure or confirmation mechanism in the manifest. Combined with broad triggers, this can cause users to initiate external messaging without understanding that a send operation will occur.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The daily_research chain automatically emails summaries as part of a triggerable workflow, which is a side effect outside the expected function of a skill router. Because this chain can be activated by broad keywords, it increases the risk of unintentional outbound transmission of generated or aggregated content.

Vague Triggers

Medium
Confidence
91% confidence
Finding
Using a single vague keyword for manual_review makes the chain easy to activate accidentally from normal language. While the chain itself is not highly dangerous, ambiguous routing can cause unexpected tool execution and reduce user control over which workflow is selected.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The module description and all user-facing documentation/comments are written entirely in Chinese and describe the classifier as tailored to Chinese medical research scenarios. There is no indication that users can choose another language or that the Chinese-only behavior is optional, which can violate language/locale policy for general-purpose skills.

Static analysis

No suspicious patterns detected.