Back to skill

Security audit

Smart Router

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent remote-model router, but it can automatically send broad user prompts and images to a configured provider without clear consent boundaries or HTTPS enforcement.

Review this before installing if you handle private, regulated, or business-sensitive content. Configure only trusted HTTPS providers, use a limited API key with spending controls, and avoid letting the router automatically process sensitive prompts or attachments until the skill documents clear consent and routing boundaries.

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
scripts/call-model.sh:100
Finding
API Credentials and User Content Can Be Transmitted Over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sync-models.sh:28-29`; `scripts/call-model.sh:100-103, 128-131, 163-166, 193-197` **Vulnerability Type**: Missing transport security enforcement for sensitive network requests **Risk Level**: High ### Vulnerable Code From `scripts/sync-models.sh:28-29`: ```bash response=$(curl -sS --max-time 30 "$BASE_URL/models" \ -H "Authorization: Bearer $API_KEY") ``` From `scripts/call-model.sh:100-103`: ```bash response=$(curl -sS --max-time 120 "$BASE_URL/chat/completions" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$body") ``` From `scripts/call-model.sh:128-131`: ```bash response=$(curl -sS --max-time 180 "$BASE_URL/images/generations" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$body") ``` From `scripts/call-model.sh:163-166`: ```bash response=$(curl -sS --max-time 300 "$BASE_URL/chat/completions" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$body") ``` From `scripts/call-model.sh:193-197`: ```bash curl -sS --max-time 120 "$BASE_URL/audio/speech" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$body" \ -o "$outfile" ``` ### Technical Analysis The scripts take `BASE_URL` from an environment variable and use it without validating the URL scheme. Consequently, a value beginning with `http://` is accepted. Every request includes the provider API key in an HTTP `Authorization` header. Model calls can additionally transmit user prompts, text intended for speech synthesis, image URLs, and other task content. If plaintext HTTP is used, network traffic is neither confidential nor protected against modification. Sending an API key to a configured provider is necessary for the declared remote-model functionality, and no hidden or hardcoded exfiltration endpoint was found. The vulnerability is the failure to enforce secure transport ...[truncated 1156 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse and validate `BASE_URL` before making any request. 2. Require the URL to use `https://` by default. 3. If local development requires plaintext HTTP, permit it only for loopback addresses through an explicit opt-in flag. 4. Reject malformed URLs, URLs containing embedded credentials, and unexpected schemes such as `file://`. 5. Consider implementing an optional allowlist of trusted provider hostnames. 6. Configure `curl` to require modern TLS, for example: ```bash case "$BASE_URL" in https://*) ;; http://127.0.0.1:*|http://localhost:*) [[ "${SMART_ROUTER_ALLOW_INSECURE_LOCALHOST:-0}" == "1" ]] || { echo "Plaintext HTTP requires explicit localhost opt-in" >&2 exit 1 } ;; *) echo "SMART_ROUTER_BASE_URL must use HTTPS" >&2 exit 1 ;; esac curl --proto '=https' --tlsv1.2 ... ``` 7. Document clearly that prompts, image URLs, and generated-task content are disclosed to the configured external provider. 8. Use provider credentials with the narrowest available permissions, spending limits, and expiration period. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/call-model.sh:143
Finding
Predictable Temporary Files Allow Symlink Overwrites and Local Data Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/call-model.sh:143-145, 191-197`; `scripts/sync-models.sh:66-67` **Vulnerability Type**: Unsafe temporary-file creation **Risk Level**: Medium ### Vulnerable Code From `scripts/call-model.sh:143-145`: ```bash local outfile="/tmp/smart-router-img-$(date +%s).png" echo "$b64" | base64 -d > "$outfile" echo "Image saved: $outfile" ``` From `scripts/call-model.sh:191-197`: ```bash local outfile="/tmp/smart-router-tts-$(date +%s).mp3" curl -sS --max-time 120 "$BASE_URL/audio/speech" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "$body" \ -o "$outfile" ``` From `scripts/sync-models.sh:66-67`: ```bash echo "Full list saved to /tmp/smart-router-models.json" echo "$response" | jq '.data | sort_by(.id)' > /tmp/smart-router-models.json ``` ### Technical Analysis Generated image and audio files use names based only on the current Unix timestamp in seconds. These names are predictable and may collide when multiple operations execute within the same second. The model-list output uses a completely fixed path. The scripts do not create these files exclusively, verify that the destination is a regular file owned by the invoking user, or establish restrictive permissions before writing. Shell redirection and `curl -o` can therefore follow a pre-existing symbolic link. On a multi-user system, another local user can pre-create the expected path as a symbolic link to a file writable by the Skill's user. The subsequent operation overwrites that target with API output. Depending on the invoking user's `umask`, generated media or provider model metadata may also be readable by other local users. ### Attack Path 1. A local attacker identifies the fixed model-list path or predicts the image or audio filename from the current timestamp. 2. The attacker creates a symbolic link at that path pointing to a file writable by the user who will invoke the Skill. 3. The victim invo ...[truncated 1035 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set a restrictive file-creation mask at script startup: ```bash umask 077 ``` 2. Use `mktemp` rather than fixed or timestamp-derived paths: ```bash outfile=$(mktemp "${TMPDIR:-/tmp}/smart-router-img.XXXXXX.png") ``` ```bash outfile=$(mktemp "${TMPDIR:-/tmp}/smart-router-tts.XXXXXX.mp3") ``` ```bash models_file=$(mktemp "${TMPDIR:-/tmp}/smart-router-models.XXXXXX.json") ``` 3. Prefer a private, user-owned output directory with mode `0700` rather than the shared `/tmp` directory. 4. Verify that temporary-file creation succeeds before downloading or decoding content. 5. Add cleanup traps for partially written files: ```bash trap 'rm -f -- "${outfile:-}"' EXIT ``` 6. If output must persist, move it atomically from the secure temporary path to a user-selected destination after successful validation. 7. Avoid reusing an existing destination unless the user explicitly requests overwrite behavior. 8. Run the Skill as an unprivileged user so any potential overwrite remains limited to that user's files. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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 (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The declared description centers on an 'intelligent multi-model router' that automatically chooses among 35+ models by task type and supports alias-based model selection. This code chunk does not do that. It only accepts an explicit --model argument and forwards requests to standard OpenAI-compatible endpoints. Supported behaviors are limited to chat, optional image input for vision-style chat, image generation, a simple chat-completions call labeled async, and TTS. There is no evidence of automatic routing, task classification, alias parsing, model catalog use beyond reading provider env var names from models.json, or video generation. Thus the actual behavior is materially narrower and different from the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description is about a runtime smart router that chooses the best model for different task types and supports alias-based model selection. The supplied code chunk does not implement routing behavior at all. Instead, it is a maintenance/discovery script used to fetch and inspect the provider's available models, group them by keyword-based categories, and save the results locally. While this may support the broader router skill by helping maintain its model catalog, the chunk's primary purpose is materially different from the declared end-user functionality. Therefore this code chunk is a mismatch with the declared description.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill encourages routing prompts, images, and generation requests to arbitrary OpenAI-compatible endpoints, but it does not warn users that their content may be transmitted to third-party providers. In this context, the omission is dangerous because the skill is explicitly designed to handle user messages and images, increasing the chance that sensitive or regulated data is sent off-platform without informed consent.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The README says the router 'kicks in automatically' for normal conversation, but does not clearly define activation boundaries, consent, or how routing decisions are constrained. In a skill that can redirect prompts and attachments to different external model providers, vague auto-activation increases the chance of unintended handling of sensitive inputs, unexpected provider selection, or bypass of user expectations about which model/service receives their data.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger table routes broad everyday requests like translation, summarization, writing, Q&A, design poster, debugging, and deep analysis without clear exclusion conditions or negative examples. Because these are common phrases across many contexts, the skill may activate unintentionally rather than only when the user specifically wants external model routing.

External Transmission

Medium
Category
Data Exfiltration
Content
if [[ -z "$BASE_URL" ]]; then
  echo "Error: environment variable $BASE_URL_ENV is not set" >&2
  echo "Set it to your OpenAI-compatible API base URL (e.g. https://api.openai.com/v1)" >&2
  exit 1
fi
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
if [[ -z "$BASE_URL" ]]; then
  echo "Error: environment variable $BASE_URL_ENV is not set" >&2
  echo "Set it to your OpenAI-compatible API base URL (e.g. https://api.openai.com/v1)" >&2
  exit 1
fi
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
'{model: $model, messages: $messages, max_tokens: $max_tokens, temperature: $temperature}')

  local response
  response=$(curl -sS --max-time 120 "$BASE_URL/chat/completions" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d "$body")
Confidence
94% confidence
Finding
This call transmits prompt content and optional image data to an external service using a user-configurable base URL and bearer token. The main danger is data exfiltration or accidental disclosure of sensitive inputs to an untrusted or misconfigured endpoint, which is more significant in a router skill designed to forward arbitrary user requests.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script sends user prompts and optional image URLs directly to a configurable remote API endpoint without any in-script disclosure, confirmation, or trust restriction. In this skill context, routing user content to arbitrary OpenAI-compatible endpoints increases privacy and data-handling risk, especially if the endpoint is self-hosted or third-party.

External Transmission

Medium
Category
Data Exfiltration
Content
'{model: $model, prompt: $prompt, size: $size, n: 1}')

  local response
  response=$(curl -sS --max-time 180 "$BASE_URL/images/generations" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d "$body")
Confidence
92% confidence
Finding
Image-generation requests send user prompts to an external provider without any trust validation of the destination. If the configured endpoint is malicious or insecure, user content may be logged, retained, or repurposed without consent.

External Transmission

Medium
Category
Data Exfiltration
Content
'{model: $model, messages: [{"role": "user", "content": $prompt}], stream: false}')

  local response
  response=$(curl -sS --max-time 300 "$BASE_URL/chat/completions" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d "$body")
Confidence
93% confidence
Finding
The async/chat path also forwards user-supplied content to an external endpoint controlled by configuration. In a multi-model routing skill, this broad forwarding behavior can expose sensitive task content to third parties if provider configuration is unsafe.

External Transmission

Medium
Category
Data Exfiltration
Content
local outfile="/tmp/smart-router-tts-$(date +%s).mp3"

  curl -sS --max-time 120 "$BASE_URL/audio/speech" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d "$body" \
Confidence
88% confidence
Finding
The TTS function sends prompt text to a remote audio endpoint and writes the returned file locally. The transmission itself is the primary concern, since potentially sensitive text may be disclosed to a third-party service without explicit warning in the script.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The script retrieves an API credential from an environment variable and uses it for authenticated outbound requests. Although missing credentials produce an error, there is no explicit disclosure in the help text or comments warning users that the skill consumes authentication material from the environment.

Static analysis

No suspicious patterns detected.