Back to skill

Security audit

Arya Model Router

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent local model-routing helper, but its documented shell integration can turn untrusted user text into command execution if copied literally.

Review this before installing if an agent or wrapper will invoke it automatically. Do not copy the README shell command with raw user text interpolation; call router.py with a structured argument array or pass text over stdin. Also decide whether automatic sub-agent/model escalation and local state.json persistence fit your cost and privacy expectations.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
README.md:39
Finding

Shell Command Injection Through Unsafe User Message Interpolation

Content
View full analysis
" --context-chars 65000 ``` ### Technical Analysis The documented integration instructs an agent to substitute an untrusted user message directly into a shell command enclosed by double quotes. Double quotes do not prevent shell command substitution: constructs such as `$(command)` and backticks are evaluated by the shell before `router.py` receives the value of `--text`. For example, if a user message contains `$(id)`, direct substitution produces: ```bash python3 skills/arya-model-router/router.py --text "$(id)" --context-chars 65000 ``` The shell executes `id` first and passes its output to the Python script. More harmful commands could be substituted in the same way. The Python implementation does not itself execute the message, but it cannot protect against expansion that already occurred in the invoking shell. ### Attack Path 1. An attacker submits a message containing shell substitution syntax, such as `$(malicious_command)`. 2. An integrating agent or application follows the documented command and inserts the message into the quoted `--text` argument. 3. The command is executed through a shell. 4. The shell evaluates the attacker-controlled substitution before starting Python. 5. The injected command runs with the permissions and environment of the integrating agent. 6. Only the resulting command output is supplied to `router.py`, potentially concealing the original injection from application-level processing. This path applies when the documented placeholder is implemented through string interpolation followed by shell execution. Invocation through a correctly constructed argument array is not vulnerable to this issue. ### Impact Assessment Successful exploitation provides ...[truncated 628 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · router.py (reported line 89)May include surrounding context.

python
th['heavy_score'] = heavy
    th['default_score'] = default
    rules['thresholds'] = th
    return rules


def score_text(text: str, rules: dict):

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Content

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

md
## Notes

- This router is safe: it does not execute arbitrary commands or call external services.
- It only emits decisions.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language content throughout the file is presented in Spanish, including the description, objectives, approach, and usage examples. This effectively imposes a language choice on users without any opt-in, alternative language option, or justification for a Spanish-only scope.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The activation examples are very broad and do not define boundaries, exclusions, or a precise invocation format. In a routing skill that can influence model selection and potentially trigger sub-agents, ambiguous triggers can cause accidental activation on unrelated user text, leading to unintended delegation, higher-cost model use, or unexpected handling of sensitive context.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring states "This script is local-only: it does not call models. It outputs a JSON decision," which implies a decision-only local router. However, the implementation also writes state changes to state.json for mode toggles, feedback updates, and lastDecision persistence. This is an active contradiction about side effects, not merely omitted detail.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This Python file contains multiple user-visible reason strings in Spanish, such as "texto largo", "patrones de matemáticas/cálculo", and "keywords pesadas detectadas". The file does not offer a language choice or document a justified Spanish-only locale restriction, which can violate the language/locale policy for skills expected to operate without forcing a specific language.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The example @cheap resume esto is a Spanish-language invocation, and the README does not indicate that language selection is optional or user-controlled. This can imply a fixed language/locale behavior without explicit opt-in, which falls under the language/locale policy check.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The config uses natural-language routing keywords in Spanish and English only, which can implicitly privilege those languages without offering user opt-in or documenting a justified locale restriction. This matches the language/locale policy concern because the skill behavior depends on fixed language assumptions embedded in config values.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.