Back to skill

Security audit

Skill Radar

Security checks for vulnerabilities and agentic risk

Overview

Skill Radar has a coherent routing purpose, but it asks agents to automatically run a shell command containing raw user input and has broad routing/server authority that needs review before installation.

Install only if you control the agent integration and can harden it. Do not use the self-routing shell command template as written; invoke the router through structured arguments with shell processing disabled or through the Python SDK. Keep the HTTP service localhost-only unless you add authentication and request limits, restrict the skills directory to trusted skills, and review routing.yaml patterns for broad matches or expensive regexes.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:37
Finding

Shell Command Injection Through Raw User Query Interpolation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:37-48
Vulnerability Type: Shell command injection
Risk Level: High

Vulnerable Code:

markdown
### Step 1: Run the router

Execute the routing script with the user's query:

```bash
python3 {SKILL_DIR}/skill_radar/cli.py route "{USER_QUERY}" --skills-dir {SKILLS_DIR} --format json

Where:

  • {SKILL_DIR} = the directory where this skill (skill-radar) is installed
  • {SKILLS_DIR} = the directory containing all other skills (each with a routing.yaml)
  • {USER_QUERY} = the user's raw input text
text

### Technical Analysis

The self-routing protocol instructs the agent to interpolate the user's raw input into a shell command. Double quotes do not neutralize every shell metacharacter. In particular, command substitution expressions such as `$(command)` and backtick substitutions remain active inside double-quoted shell arguments.

Consequently, if an agent follows this documented command by constructing and executing a shell command string, a malicious query can cause the shell to execute attacker-selected commands before the routing CLI receives the query.

The Python CLI does not independently invoke a shell, so exploitation depends on the host agent implementing this instruction through a shell command string. Nevertheless, the affected integration mode explicitly directs shell-capable agents to perform this interpolation and defines `{USER_QUERY}` as unmodified raw input.

### Attack Path

1. Skill Radar is active in self-routing mode.
2. An attacker submits a query containing shell command substitution, for example a query containing `$(id)`.
3. The agent substitutes the raw query into the documented command template.
4. The agent executes the resulting text through a shell.
5. The shell evaluates the embedded command substitution before launching Python.
6. The injected command executes with the operating-system privileges and envi
...[truncated 881 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not construct a shell command by interpolating user-controlled text.

  • Invoke the CLI through an argument-array API with shell processing disabled. For example:

    python
    subprocess.run(
        [
            sys.executable,
            str(skill_dir / "skill_radar" / "cli.py"),
            "route",
            user_query,
            "--skills-dir",
            str(skills_dir),
            "--format",
            "json",
        ],
        shell=False,
        check=True,
        text=True,
        capture_output=True,
    )
    
  • Prefer passing the query through standard input or a structured JSON input channel rather than embedding it in a command line.

  • Revise SKILL.md to explicitly prohibit shell=True, string-based command construction, and direct interpolation of raw user input.

  • If a particular framework only accepts shell text, use a trusted platform-specific argument-escaping function. Manual quoting with double quotes is insufficient.

  • Apply the same safe handling to {SKILL_DIR} and {SKILLS_DIR}, since paths may also contain shell-sensitive characters.

  • Add integration tests containing command substitutions, quotes, semicolons, newlines, and other shell metacharacters to verify that they are passed to the router literally.

T09 · Insecure Skill Coding Practices

Warning
Location
skill_radar/core.py:138
Finding

Denial of Service Through Unrestricted Backtracking Regular Expressions

Content
View full analysis

Vulnerability Details

File Locations: skill_radar/loader.py:31-39, skill_radar/loader.py:60-69, skill_radar/core.py:138-181
Vulnerability Type: Regular-expression denial of service
Risk Level: Medium

Vulnerable Code:

python
# Priority: standalone routing.yaml
if routing_yaml.exists():
    with open(routing_yaml, "r", encoding="utf-8") as f:
        data = yaml.safe_load(f)
        if data and "routing" in data:
            routing_data = data["routing"]
            skill_name = data.get("name", skill_dir.name)
        elif data and "keywords" in data:
            routing_data = data
python
return RoutingConfig(
    name=skill_name,
    keywords=routing_data.get("keywords", []),
    patterns=routing_data.get("patterns", []),
    intents=routing_data.get("intents", []),
    anti_patterns=routing_data.get("anti_patterns", []),
    anti_keywords=routing_data.get("anti_keywords", []),
    priority=routing_data.get("priority", 50),
    weight_overrides=routing_data.get("weight_overrides", {}),
python
# Anti-pattern hard exclusion
for ap in skill.anti_patterns:
    try:
        if re.search(ap, query, re.IGNORECASE):
            return ScoringResult(
                skill_name=skill.name, total_score=0.0,
                keyword_score=0.0, pattern_score=0.0, intent_score=0.0,
                context_score=0.0, priority_score=0.0,
                excluded=True, exclude_reason=f"anti_pattern: {ap}",
            )
    except re.error:
        if ap.lower() in query.lower():
            return ScoringResult(
                skill_name=skill.name, total_score=0.0,
                keyword_score=0.0, pattern_score=0.0, intent_score=0.0,
                context_score=0.0, priority_score=0.0,
                excluded=True, exclude_reason=f"anti_pattern (text): {ap}",
            )

# Keyword scoring
matched_keywords = []
if skill.keywor
...[truncated 3381 chars]
Remediation
View remediation

Remediation Suggestions

  • Define and enforce a strict schema for every routing configuration before constructing RoutingConfig.
  • Require patterns and anti_patterns to be bounded lists of strings.
  • Set conservative limits on the number of expressions, expression length, and maximum query length.
  • Compile all expressions during configuration loading and reject invalid expressions before registering a skill.
  • Prefer a regular-expression engine with guaranteed linear-time behavior for untrusted patterns.
  • If Python-compatible backtracking expressions must be retained, perform matching in an isolated worker with a strict execution timeout and terminate workers that exceed the limit.
  • Reject dangerous expression structures such as nested ambiguous quantifiers and repeated wildcard groups. Static checks should be treated as defense in depth rather than a complete substitute for timeouts.
  • Catch timeout and resource-limit failures per skill so one malformed declaration does not block the entire routing operation.
  • Add HTTP request-size limits and enforce a maximum query length before invoking the router.
  • Add security tests using known catastrophic-backtracking patterns and long nonmatching inputs.
  • Treat third-party routing declarations as untrusted configuration and review them during skill installation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
60% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

text

```bash
curl -X POST http://localhost:8900/route \
  -H "Content-Type: application/json" \
  -d '{"query": "production service returning 500 errors", "context": {"file_types": [".log"]}}'

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Running a network-accessible HTTP service and exposing routing/skill-enumeration endpoints is a materially broader capability than a local routing helper. In a meta-skill context, exposing registered skills and metadata over HTTP increases reconnaissance and remote interaction risk, especially if operators expected only local prompt-routing behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Running a network-accessible HTTP service and exposing routing/skill-enumeration endpoints is a materially broader capability than a local routing helper. In a meta-skill context, exposing registered skills and metadata over HTTP increases reconnaissance and remote interaction risk, especially if operators expected only local prompt-routing behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Running a network-accessible HTTP service and exposing routing/skill-enumeration endpoints is a materially broader capability than a local routing helper. In a meta-skill context, exposing registered skills and metadata over HTTP increases reconnaissance and remote interaction risk, especially if operators expected only local prompt-routing behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Running a network-accessible HTTP service and exposing routing/skill-enumeration endpoints is a materially broader capability than a local routing helper. In a meta-skill context, exposing registered skills and metadata over HTTP increases reconnaissance and remote interaction risk, especially if operators expected only local prompt-routing behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Running a network-accessible HTTP service and exposing routing/skill-enumeration endpoints is a materially broader capability than a local routing helper. In a meta-skill context, exposing registered skills and metadata over HTTP increases reconnaissance and remote interaction risk, especially if operators expected only local prompt-routing behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file content advertises and defines a different skill ('code-review') than the installed skill metadata ('skill-radar'), creating a skill identity mismatch. In a routing-layer skill that is loaded before other skills and influences which skills enter context, this kind of confusion can cause incorrect capability loading, misrouting, or accidental trust in the wrong instructions, which is a meaningful integrity risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

text

```bash
curl -X POST http://localhost:8900/route \
  -H "Content-Type: application/json" \
  -d '{"query": "production service returning 500 errors", "context": {"file_types": [".log"]}}'

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to invoke local Python code, read skill directories, generate files, and optionally run an HTTP service, but it declares no tool or permission scope. In a meta-skill that executes before other skills load, undeclared capabilities are especially risky because they expand trust and execution surface at a privileged point in the agent lifecycle.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill tells the agent to execute a shell command using raw user input as an argument to a Python CLI. Even if quoted in documentation, instructing shell execution at runtime is a meaningful expansion of capability for a routing layer and creates a path to command/argument injection or unsafe execution depending on the host framework's implementation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill directs the agent to run a shell command automatically on every qualifying query without clear user-facing disclosure or consent. In a meta-skill that intercepts queries before other skills load, undisclosed command execution is particularly sensitive because it happens early and can become a hidden default behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The HTTP microservice mode adds server functionality beyond the narrow description of a routing layer and expands the externally reachable attack surface. In this skill's context, that extra surface is more dangerous because the service may reveal installed skills and routing behavior that influence agent control flow.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This manifest template suggests placeholder keywords like "keyword1", "keyword phrase", and "alternate term" without emphasizing that triggers should be narrow and domain-specific. Because the file is a routing template, these examples may lead authors to define broad substring triggers that overlap with ordinary language and cause unintended skill invocation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The overall routing definition relies on ambiguous review-oriented phrases and loose regex proximity checks without clear activation boundaries. In a meta-routing skill, this is more dangerous than in an ordinary skill because it can preemptively steer the agent to load only selected skills, creating denial of intended functionality or incorrect skill selection across many user queries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The routing keywords include very broad terms like "bug" and especially "code", which are likely to match many unrelated user requests. Because this meta-skill intercepts queries before other skills are loaded, overbroad triggers can cause unintended invocation and misroute requests into a code-review path that was not intended by the user.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The keywords on these lines include broad phrases like "design review" and especially "usability", which can match many ordinary requests that are not specifically about UI/UX critique. In this meta-skill context, overbroad routing is security-relevant because this skill runs before others and can wrongly capture queries, suppressing more appropriate skills and influencing downstream agent behavior.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The pattern "(look at|check|evaluate).{0,6}(page|screen|layout|component|design)" uses very generic verbs and objects, making accidental activation likely from common requests that are not actually seeking UI-feedback skill behavior. Because skill-radar intercepts queries before other skills load, a false match can distort skill selection and reduce the availability of safer or more relevant skills.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest focuses on intercepting queries and loading top-matching skills, but cmd_init writes routing.yaml files for skills and can overwrite existing ones with --force. This is authoring/modification functionality for other skills' configuration, not merely runtime routing behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes a meta-skill that intercepts queries, scores available skills, and selects which skills to load. This file also implements a serve command that starts an HTTP routing service, which is a distinct network-exposed operation not reflected in the stated description of a routing layer for agents.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown/manifest content describes the skill's purpose broadly but does not specify how or when the skill should be invoked, nor does it provide boundaries or exclusion conditions. The generic description of reviewing code, pull requests, or snippets could overlap with many routine developer requests and may lead to unintended activation.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description says the skill can query weather 'for any location,' but it does not specify how the skill is invoked, what phrases trigger it, or any boundaries on when it should activate. In a markdown skill description, this broad natural-language scope can lead to ambiguous matching against common user requests about weather.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
85% confidence
Finding

The build dependency on wheel is specified without an exact reviewed version, so the resolved package may vary by environment and time. That makes the security state of the build toolchain unverifiable and can expose builds to known issues in affected wheel releases, though this is less severe than a direct runtime vulnerability.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: wheel has 4 known advisory(ies) (CVE-2026-24049 (Wheel Affected by Arbitrary File Permission Modification via Path Traversal in w); CVE-2022-40898 (pypa/wheel vulnerable to Regular Expression denial of service (ReDoS)); CVE-2022-40898 (An issue discovered in Python Packaging Authority (PyPA) Wheel 0.37.1 and earlie) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
85% confidence
Finding

The build dependency on wheel is specified without an exact reviewed version, so the resolved package may vary by environment and time. That makes the security state of the build toolchain unverifiable and can expose builds to known issues in affected wheel releases, though this is less severe than a direct runtime vulnerability.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: pyyaml has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The project declares PyYAML with a lower bound only (pyyaml>=6.0), so consumers may resolve different versions over time and the manifest alone does not prove that a non-vulnerable release will always be installed. In an agent-routing skill, YAML is a plausible configuration format, and PyYAML has a history of unsafe parsing issues, so leaving the dependency unpinned weakens supply-chain assurance even though this file does not itself demonstrate unsafe API usage.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.