Back to skill

Security audit

Adaptive Routing

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a local/cloud routing helper, but it can send sensitive prompts to cloud paths without clear consent and includes an unsafe remote installer command.

Review this skill before installing if you plan to use it for secrets, private business data, health data, or source code. Do not allow automatic cloud fallback for sensitive prompts unless you explicitly approve the destination provider, and avoid the documented curl-to-sh installer; use a verified package-manager or vendor install path instead.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
references/local-providers.md:7
Finding

Unverified Remote Installation Script Is Piped Directly Into a Shell

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/validate_result.py:64
Finding

Sensitive Prompts Can Be Automatically Escalated to a Cloud Provider

Content
View full analysis
= threshold: decision = "cloud" reason = f"High complexity score ({complexity}) — routing to cloud for best results" else: decision = "local" reason = f"Simple/moderate request (complexity={complexity}) — local model sufficient" ``` However, the validation component unconditionally recommends cloud escalation after any failure: ```python score = max(0.0, min(1.0, score)) passed = score >= args.min_score and len(fail_reasons) == 0 print(json.dumps({ "passed": passed, "score": round(score, 2), "reason": "ok" if passed else ", ".join(fail_reasons), "should_escalate": not passed, "validation_mode": "heuristic", "min_score": args.min_score, })) ``` The documented workflow directs the caller to perform that escalation: ```text route_request.py → local ↓ Execute with local provider ↓ validate_result.py ├── passed=true → use local result → track_savings.py log --kind local_success └── passed=false → re-run with cloud → track_savings.py log --kind escalated ``` ### Technical Analysis The sensitivity decision is not propagated into `validate_result.py`. Consequently, `should_escalate` is calculated solely from execution and response signals and is always the inverse of `passed`. A prompt can therefore be classified as sensitive and routed locally for privacy, but then be sent to a cloud provi ...[truncated 2206 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/validate_result.py:45
Finding

Claimed Quality Gate Accepts Every Non-Empty Successful Response

Content
View full analysis
= args.min_score and len(fail_reasons) == 0 print(json.dumps({ "passed": passed, "score": round(score, 2), "reason": "ok" if passed else ", ".join(fail_reasons), "should_escalate": not passed, "validation_mode": "heuristic", "min_score": args.min_score, })) ``` ### Technical Analysis The validator does not evaluate correctness, relevance, completeness, factuality, policy compliance, output structure, or correspondence to the original task. It only checks externally supplied process flags and whether the response contains at least one non-whitespace character. As a result, any non-empty response receives a score of `1.0` when the caller supplies an exit code of zero and no timeout or tool-error flag. Examples that pass include an irrelevant sentence, a fabricated answer, an incomplete result, malformed structured data, or adversarial instructions emitted by a compromised local provider. The `--min-score` option does not address this weakness because the score remains `1.0` for every non-empty response without reported process errors. The implementation is therefore an availability and transport-health check, not the advertised response-quality gat ...[truncated 1435 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code only performs service discovery for three local providers by querying localhost endpoints and listing models. While this is related to the declared ecosystem of supported local providers, it does not implement the skill's main described behavior: routing requests, validating local output quality, escalating to cloud on failure, or tracking outcomes in a persistent dashboard. This is a material description-behavior mismatch because the supplied code chunk represents only a small supporting check, not the declared primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description centers on an adaptive execution pipeline: send requests to a local model first, inspect the returned answer, and only then escalate to cloud if quality is insufficient, while persistently tracking outcomes in a dashboard. The supplied code does something much narrower: it is a standalone command-line decision helper that chooses either local or cloud upfront using heuristic complexity and sensitivity checks. It never invokes a model, never inspects a response, and never performs retry/escalation after a failed local attempt. It also does not store metrics, update any dashboard, or report savings. While local/cloud routing is related to the declared theme, the core promised behaviors—quality validation, fallback based on actual output, persistent tracking, and provider support beyond a label—are absent, making this a material description/behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a full adaptive-routing system for LLM inference, including local provider support, quality validation, fallback to cloud, and dashboard tracking. The supplied code chunk only implements the tracking portion: a command-line script that records outcome kinds, token counts, estimated cloud cost savings, and persists them to ~/.openclaw/adaptive-routing/savings.json. While this partially aligns with the tracking/dashboard aspect, the primary advertised capabilities—routing, validation, escalation logic, and provider support—are absent from this code. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Content

Scanner excerpt · SKILL.md (reported line 55)May include surrounding context.

bash
# Local success (no escalation needed)
python3 skills/adaptive-routing/scripts/track_savings.py log \
  --kind local_success --tokens 800 --model gpt-4o

# Escalated (local failed validation, used cloud)
python3 skills/adaptive-routing/scripts/track_savings.py log \

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Content

Scanner excerpt · SKILL.md (reported line 59)May include surrounding context.

Escalated (local failed validation, used cloud)

python3 skills/adaptive-routing/scripts/track_savings.py log
--kind escalated --tokens 800 --model gpt-4o

text

### 6. Show the dashboard

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

curl -fsSL https://ollama.ai/install.sh | sh fetches a remote script and immediately executes it without prior inspection, integrity verification, or pinning. If the host, network path, or downloaded script is compromised, users can suffer arbitrary code execution on their machine during installation.

Content

Scanner excerpt · references/local-providers.md (reported line 12)May include surrounding context.

brew install ollama

Linux

curl -fsSL https://ollama.ai/install.sh | sh

text

**Start server**

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The | sh pipeline is dangerous because it turns remotely fetched content directly into shell commands, eliminating the user's opportunity to review what will run. In a setup guide, this normalizes a risky pattern that can lead to immediate system compromise if the fetched content is malicious or tampered with.

Content

Scanner excerpt · references/local-providers.md (reported line 12)May include surrounding context.

brew install ollama

Linux

curl -fsSL https://ollama.ai/install.sh | sh

text

**Start server**

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation instructs use of shell commands, network calls, and persistent file writes, yet it declares no explicit tool scope or permissions boundary. This creates a trust and review gap: an agent may execute capabilities broader than a user expects, including writing routing state under the home directory and sending prompts to local HTTP services.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill persists configuration and, elsewhere in the document, savings/outcome data under ~/.openclaw/adaptive-routing. Persistent storage can retain sensitive routing metadata, prompt-related statistics, and operational preferences across sessions, which may expose privacy-sensitive usage patterns on shared systems or through overly permissive file permissions.

Content

Scanner excerpt · SKILL.md (reported line 120)May include surrounding context.

Configuration

Create ~/.openclaw/adaptive-routing/config.json to tune thresholds:

json
{

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 · SKILL.md (reported line 142)May include surrounding context.

Ollama

bash
curl http://localhost:11434/api/generate \
  -d '{"model": "llama3.2", "prompt": "YOUR_PROMPT", "stream": false}'

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 · references/local-providers.md (reported line 33)May include surrounding context.

Test

bash
curl http://localhost:11434/api/generate \
  -d '{"model":"llama3.2","prompt":"Hello","stream":false}'

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/routing-logic.md (reported line 11)May include surrounding context.

md
Each request is scored. Higher = more complex = prefer cloud.

| Factor                                                                                                                                                                                   | Score Change |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| Keyword match: `analyze`, `synthesize`, `compare`, `reason`, `architecture`, `code review`, `multi-step`, `evaluate`, `critique`, `refactor`, `design`, `implement`, `debug`, `strategy` | +2 per match |
| Keyword match: `summarize`, `translate`, `list`, `what is`, `define`, `explain briefly`, `convert`, `format`, `reformat`, `spell check`                                                  | −1 per match |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/routing-logic.md (reported line 15)May include surrounding context.

md
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| Keyword match: `analyze`, `synthesize`, `compare`, `reason`, `architecture`, `code review`, `multi-step`, `evaluate`, `critique`, `refactor`, `design`, `implement`, `debug`, `strategy` | +2 per match |
| Keyword match: `summarize`, `translate`, `list`, `what is`, `define`, `explain briefly`, `convert`, `format`, `reformat`, `spell check`                                                  | −1 per match |
| Token count > `token_high_watermark` (default 4,000)                                                                                                                                     | +2           |
| Token count < `token_low_watermark` (default 500)                                                                                                                                        | −1           |

### Decision Tree

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/routing-logic.md (reported line 16)May include surrounding context.

md
| Keyword match: `analyze`, `synthesize`, `compare`, `reason`, `architecture`, `code review`, `multi-step`, `evaluate`, `critique`, `refactor`, `design`, `implement`, `debug`, `strategy` | +2 per match |
| Keyword match: `summarize`, `translate`, `list`, `what is`, `define`, `explain briefly`, `convert`, `format`, `reformat`, `spell check`                                                  | −1 per match |
| Token count > `token_high_watermark` (default 4,000)                                                                                                                                     | +2           |
| Token count < `token_low_watermark` (default 500)                                                                                                                                        | −1           |

### Decision Tree

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/dashboard.py (reported line 14)May include surrounding context.

python
def run(args: list) -> dict:
    try:
        result = subprocess.run(
            [PY] + args, capture_output=True, text=True, timeout=5
        )
        return json.loads(result.stdout) if result.returncode == 0 and result.stdout.strip() else {}

Static analysis

No suspicious patterns detected.