Back to skill

Security audit

OpenClaw Hook Examples

Security checks for vulnerabilities and agentic risk

Overview

This is a documentation-only skill with hook examples; its risky snippets are illustrative and not installed or executed by the package.

Install only as documentation or examples. If adapting the snippets, redact sensitive tool parameters and session identifiers before logging, and replace substring command checks with scoped allowlists, sandboxing, and explicit user approval for dangerous operations.

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

Warning
Location
SKILL.md:22
Finding

Unredacted Tool Parameters and Session Identifiers Written to Logs

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 22-33
Vulnerability Type: Sensitive information exposure through logging
Risk Level: Medium

Vulnerable Code

javascript
api.registerHook("before_tool_call", async ({ event, ctx }) => {
  const log = {
    time: new Date().toISOString(),
    tool: event.tool.name,
    params: event.tool.params,
    session: ctx.sessionKey
  };
  // Write to log file
  console.log("[TOOL_AUDIT]", JSON.stringify(log));
  return {}; // Don't block, continue execution
});

Technical Analysis

The audit hook serializes the complete event.tool.params object and ctx.sessionKey without filtering or redaction. Tool parameters can contain authentication tokens, passwords, private file contents, personal data, command arguments, or other sensitive values.

Console output is commonly retained by process supervisors, container platforms, CI systems, or centralized logging services. Consequently, information originally available only to the agent or tool may become accessible to every account and service permitted to read those logs.

The project only contains documentation, so this behavior is not currently executed by this package. The vulnerability arises if the example is copied into an operational plugin as presented.

Attack Path

  1. An attacker or untrusted prompt induces the agent to invoke a tool with a secret or sensitive value in its parameters.
  2. The before_tool_call hook receives the complete parameter object.
  3. JSON.stringify(log) serializes the parameters and session identifier without redaction.
  4. console.log sends the resulting record to the runtime's logging destination.
  5. An attacker, operator, compromised logging integration, or other user with log-reading access retrieves the exposed information.
  6. Any captured credentials or tokens may then be reused against the systems for which they are valid.

Impact Asse

...[truncated 517 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not log complete tool parameter objects by default.
  • Define a strict allowlist of non-sensitive fields that may be recorded, such as the tool name, timestamp, outcome, and a generated audit-event identifier.
  • Implement recursive redaction for keys such as password, secret, token, authorization, cookie, apiKey, and private-key material.
  • Omit the session key or replace it with a non-reversible, scoped audit identifier.
  • Apply maximum length limits to all logged values to prevent accidental bulk disclosure.
  • Restrict access to audit logs and configure appropriate encryption, retention, and deletion policies.
  • Add automated tests demonstrating that nested credentials and session identifiers never appear in emitted log records.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:51
Finding

Bypassable Substring Denylist Presented as Shell Command Validation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 51-66
Vulnerability Type: Insufficient validation of dangerous shell commands
Risk Level: Medium

Vulnerable Code

javascript
api.registerHook("before_tool_call", async ({ event, ctx }) => {
  if (event.tool.name === "exec") {
    const cmd = event.tool.params.command || "";
    const dangerous = ["rm -rf", "dd if=", "mkfs", ":(){:|:&}:"];
    for (const d of dangerous) {
      if (cmd.includes(d)) {
        return { 
          block: true, 
          reason: `Dangerous command pattern detected: ${d}` 
        };
      }
    }
  }
  return {};
});

Technical Analysis

The example attempts to protect an arbitrary shell-execution tool using four literal substring checks. A denylist of textual patterns cannot reliably determine the behavior of a shell command.

Semantically equivalent destructive operations can avoid these exact strings through alternate utilities, shell quoting, variable expansion, different whitespace, encoded payloads, interpreter invocation, scripts, aliases, or indirect execution. Dangerous operations not represented in the list are also permitted automatically.

Because the handler returns an empty object whenever none of the literal strings is present, any bypass proceeds to the exec tool. This validation therefore must not be treated as a security boundary.

The repository contains only documentation and does not itself execute this handler. Exploitation applies when the example is implemented in a plugin without stronger controls.

Attack Path

  1. An attacker gains influence over a prompt or other input used to construct an exec tool request.
  2. The attacker supplies a destructive or unauthorized command whose literal text does not include any of the four denylisted strings.
  3. The hook compares the command against the limited substring list.
  4. No pattern matches, so the hook returns `{ ...[truncated 972 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not use a substring denylist as the primary control for arbitrary command execution.
  • Replace shell command strings with structured process invocation using a fixed executable and separately supplied arguments.
  • Enforce a strict allowlist of permitted executables, operations, argument forms, working directories, and target resources.
  • Reject shell metacharacters and disable shell interpretation where it is not explicitly required.
  • Require explicit human approval for destructive, privileged, or policy-sensitive operations.
  • Run execution tools in an isolated sandbox with a read-only base filesystem, minimal writable directories, restricted networking, resource limits, and a dedicated unprivileged account.
  • Prevent access to host credentials and sensitive environment variables from the execution environment.
  • Add tests covering alternate whitespace, quoting, variable expansion, encoded commands, interpreter-based execution, indirect script execution, and destructive tools not present in the original list.
  • Clearly document that pattern matching may provide supplemental detection but is not an authorization or containment boundary.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep