Back to skill

Security audit

Dynamic Model Router

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent model-routing purpose, but it includes under-disclosed high-impact code paths that can execute shell commands, write prompts to shared temp files, probe arbitrary provider URLs, and persist local configuration/log data.

Review this skill carefully before installing. It may be appropriate only if you trust the publisher and are comfortable with local config/log persistence plus OpenClaw provider integration code. Do not use it with sensitive prompts or API keys until shell execution is changed to argument-based spawning, temp prompt files are protected or removed, provider URLs are strictly allowlisted, and the privacy documentation matches the actual data flows.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/openclaw-invoker.ts:297
Finding

Shell Command Injection Through Model Messages

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/openclaw-invoker.ts:484
Finding

Sensitive Prompts Written to Predictable Shared Temporary Storage

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/model-adapter.ts:269
Finding

Prompts and Bearer Credentials Sent to Unvalidated Provider URLs

Content
View full analysis
controller.abort(), this.config.timeoutMs); try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}`, 'User-Agent': 'OpenClaw-DynamicRouter/0.1.0', }, body: JSON.stringify(requestBody), signal: controller.signal, }); ``` ### Technical Analysis The destination is constructed from `provider.baseUrl`, which can originate from OpenClaw configuration. The adapter does not require HTTPS, verify that the hostname belongs to the declared provider, prevent private or link-local destinations, or restrict redirects. The request sends both the complete conversation and the provider API key. Consequently, an attacker who can alter or influence the provider configuration can direct sensitive prompts and bearer credentials to an attacker-controlled server. This behavior contradicts the Skill documentation, which states that routing is processed locally and that user data is not sent to external servers. The adapter is not re-exported by `src/openclaw/index.ts`, which reduces default exposure, but the implementation remains directly i ...[truncated 996 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/provider-discovery.ts:460
Finding

Server-Side Request Forgery in Provider Discovery

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/status-monitor.ts:322
Finding

Recurring SSRF Through the Provider Status Monitor

Content
View full analysis
{ logger.error('Initial health check failed', error as Error); }); this.monitoringInterval = setInterval(() => { this.performHealthCheck().catch(error => { logger.error('Periodic health check failed', error as Error); }); }, this.config.checkInterval); ``` ### Technical Analysis The status monitor constructs request URLs from `provider.baseUrl` without validating destination safety. Once monitoring starts, it performs an immediate request and repeats the operation every minute by default. The monitor therefore turns a configuration-controlled SSRF primitive into a recurring network action. It leaks the presence and timing of the Agent through its User-Agent and can repeatedly interact with internal or attacker-controlled services. The alert implementation only writes to the logger; it contains a TODO for external notifications. No metric exfiltration through alert channels is currently implemented. ### Attack Path 1. An attacker introduces a provider with a malicious `baseUrl`. 2. The provider and adapter are registered with `StatusMonitor`. 3. A caller invokes `startMonitoring()`. 4. The monitor immediately sends a HEAD request to the chosen destination. 5. It repeats the request according to `checkInterval`, which defaults to 60 seconds. ...[truncated 493 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openclaw/openclaw-invoker.ts:628
Finding

Arbitrary File Deletion Through Mutable Temporary Directory Configuration

Content
View full analysis
): void { this.config = { ...this.config, ...updates }; logger.debug('Invoker configuration updated', { updates }); } /** * Clean temporary files */ async cleanupTempFiles(): Promise { try { const files = await fs.promises.readdir(this.config.tempDir); const cleanupPromises = files.map(async (file) => { const filePath = path.join(this.config.tempDir, file); const stats = await fs.promises.stat(filePath); // Delete temporary files older than one hour const age = Date.now() - stats.mtimeMs; if (age > 3600000) { await fs.promises.unlink(filePath); logger.debug('Deleted old temporary file', { file, age }); } }); await Promise.all(cleanupPromises); logger.info('Temporary-file cleanup completed', { tempDir: this.config.tempDir }); ``` ### Technical Analysis `updateConfig()` permits unrestricted modification of `tempDir`. `cleanupTempFiles()` then enumerates that directory and deletes every entry older than one hour. It does not verify that the path remains inside a private temporary root, that files were created by this invoker, or that entries match the invoker's naming convention. The cleanup uses `stat()` rather than a symlink-aware ownership policy and does not maintain a registry of generated files. Destroying the singleton also invokes this cleanup method, making deletion reachable through normal lifecycle handling after malicious configuration. ### Attack Path 1. An attacker or untrusted caller obtains access to the exported invoker instance. 2. The caller invokes `updateConfig({ tempDir: targetDirectory })`. 3. The target directory contains files older than one hour that are writable by the Agent accou ...[truncated 651 chars]
Remediation
View remediation
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (96)

Known Vulnerable Dependency: handlebars==4.7.8 — 8 advisory(ies): CVE-2026-33916 (Handlebars.js has Prototype Pollution Leading to XSS through Partial Template In); CVE-2026-33937 (Handlebars.js has JavaScript Injection via AST Type Confusion); CVE-2026-33938 (Handlebars.js has JavaScript Injection via AST Type Confusion by tampering @part) +5 more

Critical
Category
Supply Chain
Confidence
97% confidence
Finding

handlebars 4.7.8 is present and has multiple severe advisories including prototype pollution and possible code or script injection through crafted templates/AST manipulation. Even as a dev dependency, this is highly dangerous if any untrusted template content is compiled or rendered during code generation, testing, or build automation.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==1.1.12 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
95% confidence
Finding

brace-expansion 1.1.12 is present and is associated with multiple denial-of-service issues involving pathological brace patterns that can trigger excessive CPU or memory consumption. Even though it is transitive and primarily in development tooling paths, it remains a real vulnerability if any code path accepts untrusted glob or pattern input.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==3.14.2 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

js-yaml 3.14.2 is included and has multiple reported CPU-exhaustion issues when parsing crafted YAML with merge keys or special structures. This is a real vulnerability in the dependency, though in this lockfile it appears under dev tooling, so exploitability depends on whether untrusted YAML is ever parsed during tests or build steps.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
95% confidence
Finding

brace-expansion 2.0.2 is also present and carries the same class of denial-of-service issues from crafted brace patterns that can consume large CPU or memory resources. Because there are multiple copies in the dependency graph, the exposure is broader across tooling that performs glob expansion.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: browserslist==4.28.1 — 2 advisory(ies): CVE-2026-73088 (Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.); CVE-2026-73089 (Browserslist: Unbounded memory growth (no cache eviction) via distinct query res)

High
Category
Supply Chain
Confidence
88% confidence
Finding

browserslist 4.28.1 is present and is reported with crash/prototype-write and unbounded-memory-growth issues when handling untrusted stats or adversarial queries. This is a real issue, but in this repository it is part of the development toolchain rather than the production skill path, which lowers the immediate exploitability.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: flatted==3.4.1 — 1 advisory(ies): CVE-2026-33228 (Prototype Pollution via parse() in NodeJS flatted)

High
Category
Supply Chain
Confidence
93% confidence
Finding

flatted 3.4.1 is reported as vulnerable to prototype pollution via parse(), which can let attacker-controlled input modify object prototypes and alter program behavior in dangerous ways. Although this instance is in dev tooling, prototype pollution is broadly dangerous because it can lead to logic bypass, unexpected property resolution, or downstream code execution conditions in some contexts.

Content

No source excerpt is available for this finding.

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 · src/routing/performance-predictor.ts (reported line 367)May include surrounding context.

ts
} as PredictedPerformance;
      } catch (error) {
        logger.warn('历史预测失败,使用规则预测', { error });
        return rulePrediction;
      }
    }

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 · src/routing/performance-predictor.ts (reported line 372)May include surrounding context.

ts
} as PredictedPerformance;
      } catch (error) {
        logger.warn('历史预测失败,使用规则预测', { error });
        return rulePrediction;
      }
    }

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The document begins entirely in Chinese and continues in Chinese throughout, with no indication that users may choose another language or that the skill is intended only for a Chinese-speaking or region-specific audience. This can violate a language/locale policy when a skill imposes a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file presents all user-facing instructions, setup steps, and API guidance exclusively in Chinese. Under the policy for natural-language violations, forcing a specific language without user opt-in or a documented justification is a reportable issue.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This manifest’s user-facing natural-language fields, including name, description, capability descriptions, configuration descriptions, and examples, are presented exclusively in Chinese. Under the policy, forcing a specific language without offering a user choice or documenting a justified locale constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code logs a preview of raw task content before routing, which can capture sensitive prompts, credentials, personal data, or proprietary text in application logs. Because this occurs automatically and there is no evidence here of consent, redaction, or log-level gating, normal use can create an unintended data exposure path.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The exported skill interface presents itself as a routing skill, but it also exposes privileged state-changing operations such as configuration mutation and shutdown. In an agent-skill context, this expands the attack surface beyond the advertised purpose and can let prompts or other skills reconfigure routing behavior persistently, disable safeguards, or induce denial of service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This TypeScript file uses Chinese throughout its descriptive comments and operational log messages, including initialization, error, and status text, with no indication that the skill is China-specific or that users can opt into this locale. Under the language/locale policy, forcing a specific language without user choice is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function defensively derives a safe modelId from multiple possible selectedModel shapes, but the created LearningSample later uses decision.selectedModel.modelId directly. If untrusted or malformed routing data reaches this path, that direct dereference can throw at runtime or record inconsistent sample data, allowing an attacker or bad input to disrupt learning, suppress telemetry, or poison model-specific statistics. In this learning/router context, availability and integrity of routing feedback are important, so this mismatch is more dangerous than a mere style issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code sends request.messages in an HTTP POST body to a third-party model provider, which may include user or system data. Although there is developer-oriented debug logging, there is no confirmation prompt or clear user-facing disclosure in this file that request contents will be transmitted externally.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

With no manifest available, this skill's purpose is unknown, so spawning subprocesses via child_process and operating on local files/temp directories are capabilities that are not justified by any stated intent. The code does more than simple in-process request handling by invoking an external binary, reading environment-derived paths, and creating local workspace/temp state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code constructs a shell command by interpolating request.model, serialized messages, numeric options, and openclawPath into a single string passed to exec. Because shell metacharacters and quoting edge cases in user-controlled content can break out of the intended arguments, this creates a command injection risk that could lead to arbitrary command execution under the application's privileges.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The invoker writes full request payloads, including conversation messages, to predictable files under a shared temp directory. This can expose sensitive prompts, system messages, API-related metadata, or proprietary data to other local users/processes and leaves recoverable artifacts on disk if cleanup fails or the process crashes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Temporary request/session files store raw user and system messages on disk without confidentiality protections or explicit lifecycle guarantees. In this context, prompts may contain secrets, personal data, or internal instructions, so storing them in /tmp-like locations materially increases local disclosure risk and post-mortem data leakage.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/openclaw/provider-discovery.ts (reported line 330)May include surrounding context.

ts
private inferBaseUrl(providerId: string): string {
    const urlMap: Record<string, string> = {
      'deepseek': 'https://api.deepseek.com',
      'openai': 'https://api.openai.com/v1',
      'anthropic': 'https://api.anthropic.com',
      'google': 'https://generativelanguage.googleapis.com',
      'mistral': 'https://api.mistral.ai/v1',

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/openclaw/provider-discovery.ts (reported line 333)May include surrounding context.

ts
'openai': 'https://api.openai.com/v1',
      'anthropic': 'https://api.anthropic.com',
      'google': 'https://generativelanguage.googleapis.com',
      'mistral': 'https://api.mistral.ai/v1',
      'cohere': 'https://api.cohere.ai',
      'minimax': 'https://api.minimax.chat/v1',
      'qwen': 'https://dashscope.aliyuncs.com/compatible-mode/v1',

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/openclaw/provider-discovery.ts (reported line 335)May include surrounding context.

ts
'google': 'https://generativelanguage.googleapis.com',
      'mistral': 'https://api.mistral.ai/v1',
      'cohere': 'https://api.cohere.ai',
      'minimax': 'https://api.minimax.chat/v1',
      'qwen': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
      'baichuan': 'https://api.baichuan-ai.com/v1',
    };