Back to skill

Security audit

A.I. Smart Router

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent model router, but it can silently send prompts to other providers and its executable delegation path bypasses the promised credential filter.

Review this skill carefully before installing. It is not backed by evidence of intentional theft or destructive behavior, but it is designed to route normal prompts among external model providers, and the shipped code has a real sanitizer bypass in the live delegation path. Avoid using it with secrets, health data, financial records, customer data, or proprietary material unless you add explicit provider allowlists, user confirmation before cross-provider routing, and a single enforced sanitization path for all delegation and fallback flows.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
executor.py:251
Finding
Credential Filtering Is Bypassed by the Live Delegation Path<![CDATA[ ## Vulnerability Details **File Location**: `executor.py:251` and `executor.py:281-289` **Vulnerability Type**: Security-control bypass causing sensitive-data disclosure **Risk Level**: High ### Vulnerable Code ```python # Get routing decision decision = self.router.classify(message, context_tokens) ``` ```python if should_delegate: self._task_counter += 1 task_id = f"router-{self._task_counter}-{int(time.time())}" agent_id = self.AGENT_IDS.get(recommended) spawn_params = { "task": message, "label": f"router-{decision.intent.name.lower()}-{recommended}", } ``` The protected gateway path sanitizes requests before processing: ```python # Sanitize input sanitized = self.sanitizer.sanitize(text) if sanitized.blocked: return RouterResponse( content=f"❌ Request blocked: {sanitized.block_reason}", model_used="none", routing_decision=RoutingDecision( intent=Intent.GENERAL, complexity=Complexity.SIMPLE, selected_model="blocked", fallback_chain=[], reason=sanitized.block_reason or "Security block" ) ) ``` ### Technical Analysis `RouterExecutor.analyze()` calls `SmartRouter.classify()` directly instead of the protected `SmartRouter.route_request()` entry point. The `classify()` method performs routing classification but does not invoke `InputSanitizer`. When delegation is selected, the executor copies the original, unfiltered `message` directly into `spawn_params["task"]`. The Agent is then expected to submit this value through OpenClaw's `sessions_spawn` mechanism. This bypasses the controls enabled by `router_config.json`: ```json "security": { "sanitize_input": true, "block_credentials": true, "warn_pii": true } ``` It also contradicts the security guarantee in `references/security.md:194` that no unsanitized input reaches a model API. Credential patterns intended to be blocked include Anthropic, OpenAI, xAI ...[truncated 1730 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Establish one mandatory input-validation entry point shared by every routing and execution path. 2. Sanitize before classification and delegation: ```python sanitized = self.router.sanitizer.sanitize(message) if sanitized.blocked: raise SecurityError(sanitized.block_reason) safe_message = sanitized.text decision = self.router.classify(safe_message, context_tokens) ``` 3. Populate delegated tasks only with the sanitized value: ```python spawn_params = { "task": safe_message, "label": f"router-{decision.intent.name.lower()}-{recommended}", } ``` 4. Return a structured blocked execution plan instead of relying on an exception if that better fits the integration API. 5. Prevent direct use of `classify()` for execution by clearly separating pure classification from the protected dispatch interface. 6. Apply the same validation to fallback and retry paths so they cannot reintroduce the original raw message. 7. Enforce configuration flags such as `sanitize_input` and `block_credentials` in executable code rather than treating them as documentation-only settings. 8. Add regression tests covering every configured credential pattern through: - `SmartRouter.route_request()` - `RouterExecutor.analyze()` - `ExecutorAgent.should_delegate()` - Fallback delegation 9. Add tests asserting that `spawn_params["task"]` never contains a blocked credential or disallowed control character. 10. Consider explicit user confirmation before sending sensitive but non-blocked content to a provider with a different trust tier. ]]>

T07 · Tool Hijacking and Spoofing

Warning
Location
dashboard.py:254
Finding
Dashboard Reports Fabricated Security-Event Counts<![CDATA[ ## Vulnerability Details **File Location**: `dashboard.py:254-265` **Vulnerability Type**: Misleading security telemetry and monitoring spoofing **Risk Level**: Medium ### Vulnerable Code ```python def _get_security_summary(self) -> dict[str, int]: """Get security event summary for today.""" # In a full implementation, this would read from a security log # For now, return placeholder based on logged decisions # These would be tracked by the sanitizer in production return { "blocked": 1, # We blocked one request in dry run "pii_warnings": 0, "credentials": 1, # The test key we caught } ``` ### Technical Analysis The dashboard presents fixed test values as if they were current security-event measurements. It always reports one blocked request and one detected credential, regardless of whether the sanitizer processed any requests or whether the live executor bypassed it. Although comments identify the implementation as a placeholder, the rendered dashboard describes these values as operational security statistics. There is no security event log or runtime counter backing the displayed results. This creates false assurance around credential filtering. It is particularly consequential because the live delegation path can bypass that filtering entirely. ### Attack Path 1. Requests are processed through the executor path that bypasses input sanitization. 2. Sensitive content can be delegated without generating a sanitizer event. 3. An operator opens the dashboard to verify whether security filtering is active. 4. `_get_security_summary()` returns fixed positive detection counts. 5. The dashboard indicates that credentials were caught and requests were blocked. 6. The operator incorrectly concludes that the security control is functioning and may not investigate the underlying exposure. The weakness does not require an attacker to alter the telemetry. The shipped implementation itself produces mislead ...[truncated 668 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove hard-coded security counters from production output. 2. Until real telemetry exists, return an explicit unavailable state rather than synthetic numbers: ```python return { "status": "unavailable", "reason": "Security event logging is not configured", } ``` 3. Add structured security-event logging at the sanitizer boundary for blocked credentials, warnings, truncation, and normalization events. 4. Derive dashboard counts from that authoritative event source. 5. Ensure security logs contain only event metadata and never store the detected credential itself. 6. Protect event logs with restrictive file permissions and defined retention limits. 7. Distinguish test, dry-run, and production events using explicit environment and source fields. 8. Display the last successful telemetry update time and report stale or unavailable data prominently. 9. Add tests proving that: - No event produces a zero count. - One blocked credential produces one count. - Executor and fallback paths generate the same events as the gateway path. - Missing telemetry never appears as a successful security-control result. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the actual skill introduces disk persistence and CLI inspection/cleanup while omitting that from the description, users and operators cannot accurately assess data retention, exposure of logs, or local attack surface. In an agent skill that may process prompts and provider metadata, undeclared persistence is a real security concern because it can store sensitive content or routing state unexpectedly.

Vague Triggers

High
Confidence
96% confidence
Finding
Silent-by-default activation means the skill may engage on ordinary user messages without explicit consent or a narrow invocation pattern. For a router that can choose external providers and inspect message content, overbroad activation increases the chance of unintended provider routing, accidental data disclosure, and unpredictable interference with other skills or system behavior.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
# Security Best Practices for Model Routing

Comprehensive security guidance for multi-model routing systems.

---

## Security Guarantees

This skill makes the following security guarantees:

| Guarantee | Status | Verification |
|-----------|--------|--------------|
| No API keys stored in skill files | ✅ Enforced | Grep for patterns; none found |
| Credentials via environment only | ✅ Enforced | Keys read from env/auth-profiles only |
| Input sanitization before routing | ✅ Implemented | See [Input Sanitization](#input-sanitization) |
| No arbitrary code execution | ✅ By design | See [Code Execution Safety](#cod
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
# __import__(user_input) # DOES NOT EXIST
```

### Model Override Safety

Even user model overrides are validated against an allowlist:
Confidence
90% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Instruction Override

High
Category
Prompt Injection
Content
# __import__(user_input) # DOES NOT EXIST
```

### Model Override Safety

Even user model overrides are validated against an allowlist:
Confidence
90% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Instruction Override

High
Category
Prompt Injection
Content
Watch for attempts to manipulate routing:

```
"Ignore previous instructions"
"You are now..."
"Disregard your programming"
"New system prompt:"
Confidence
80% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
### AI-Specific Risks

1. **Jailbreaking attempts** - Users trying to bypass safety
2. **Data exfiltration** - Tricking AI to reveal training data
3. **Model confusion** - Causing wrong model selection
4. **Cost attacks** - Triggering expensive models unnecessarily
Confidence
90% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Instruction Override

High
Category
Prompt Injection
Content
### AI-Specific Risks

1. **Jailbreaking attempts** - Users trying to bypass safety
2. **Data exfiltration** - Tricking AI to reveal training data
3. **Model confusion** - Causing wrong model selection
4. **Cost attacks** - Triggering expensive models unnecessarily
Confidence
90% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Intent-Code Divergence

High
Confidence
94% confidence
Finding
The router's classify path references undefined Phase H symbols and functions such as pre_flight_token_audit, PHASE_H_FORCE_THRESHOLD, and PHASE_H_MODEL, which will cause runtime failure before routing completes. In this skill context, that can disable routing, sanitization-dependent protections, and provider-selection safeguards, creating a denial-of-service condition and undermining the claimed safety controls.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The documentation states mandatory routing of medical requests to GPT-5.2 without offering user choice or consent. For high-sensitivity domains like health, forced provider selection can route private data to a third party based solely on router policy, creating privacy, compliance, and user-expectation risks even if the model is selected for quality reasons.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README explicitly documents a 'silent retry' that intercepts context-overflow errors and reroutes the request to Gemini without notifying the user at the moment provider handling changes. This creates a transparency and consent problem: sensitive prompts may be sent to a different provider than the user expected, undermining data-handling assumptions, auditability, and trust boundaries.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
# From your workspace root
mkdir -p skills
cp -r /path/to/smart-router skills/
```
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares runtime requirements and presents executable Python snippets and provider interactions, but does not declare an explicit tool/permission scope. In an agent environment, missing least-privilege boundaries can allow the skill to access environment variables, networked model providers, and local state/log files more broadly than users expect. The risk is amplified by references to persistent state, status commands, and provider discovery.

Vague Triggers

Medium
Confidence
90% confidence
Finding
Using broad everyday phrases like 'write', 'explain', 'review', or 'summarize' as activation/intent signals creates a high risk of unintended matching. In a skill that may route requests across providers, broad triggers can cause requests containing sensitive or irrelevant content to be processed by the router when the user did not intend that behavior.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The long-context table states that 128K-200K requests fall back through 'Opus → Sonnet → Gemini Pro' and that 200K-1M uses 'Gemini Pro → Flash'. However, the implementation at L431 includes 'haiku' and 'flash' in the <=200K tier as additional candidates, which expands behavior beyond the documented chain. This is an active intent/documentation contradiction rather than a minor omission because the section is presented as the authoritative fallback policy.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The inline comments at L625 describe COMPLEX as allowing only '$', '$$', and '$$$', but the returned mapping at L657 also includes '$$$$'. Since Opus is documented as '$$$$' elsewhere, the code permits the most expensive tier despite the nearby explanation saying otherwise. This is a direct contradiction in implementation guidance, not merely incomplete documentation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documented 'silent retry with Gemini Pro' behavior can resend failed prompts to a different provider without explicit user awareness or consent. In a router that may handle sensitive prompts, this creates a real confidentiality and compliance risk because data that the user intended for one model/provider could be transmitted to another after an error condition.

Static analysis

Detected: suspicious.prompt_injection_instructions

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
references/security.md:270