Back to skill

Security audit

Audit OpenClaw Security

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent defensive OpenClaw audit skill, but its bundled redaction and audit-collection helpers can expose sensitive data if users trust their outputs too much.

Install only if you are comfortable reviewing the generated audit folder and redacted config output before sharing. Do not treat the bundled redactor as sufficient for secrets; manually verify or remove credential values, especially short passwords, tokens, cookies, and API keys. Store collector output in a private directory because it may reveal network, firewall, plugin, and OpenClaw posture details.

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

Error
Location
scripts/redact_openclaw_config.py:37
Finding

Sensitive-key values shorter than 24 characters bypass redaction

Content
View full analysis
str: s = s or "" if len(s) <= 8: return "***" return f"{s[:4]}…{s[-4:]}" def looks_secret(s: str) -> bool: if len(s) < 24: return False if s.startswith(("http://", "https://", "/", "./", "../", "~/")): return False return bool(JWT_LIKE_RE.match(s) or HEXISH_RE.match(s) or ALNUMISH_RE.match(s)) def redact_string(s: str) -> str: if looks_secret(s): return mask(s) return URL_QS_SECRET_RE.sub(lambda m: m.group("prefix") + mask(m.group("val")), s) def redact_obj(obj: Any) -> Any: if isinstance(obj, dict): out: dict[str, Any] = {} for key, value in obj.items(): skey = str(key) if SENSITIVE_KEY_RE.search(skey): if isinstance(value, str): out[skey] = redact_string(value) else: out[skey] = "***" else: out[skey] = redact_obj(value) return out ``` ### Technical Analysis When a key matches `SENSITIVE_KEY_RE`, its string value is passed to `redact_string()` rather than being unconditionally replaced. `redact_string()` only masks a standalone value if `looks_secret()` recognizes it as secret-like. The first condition in `looks_secret()` rejects every value shorter than 24 characters. Consequently, short passwords, API keys, session keys, cookies, and tokens remain unchanged unless they happen to appear as a recognized URL query parameter. This violates the script's documented security purpose: users are instructed to run it before sharing a configuration file and may reasonably treat its output as safe. The issue affects structured JSON and JSON5 processing. Retaining four-character prefixes and suffixes for longer credentials ...[truncated 1443 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/collect_openclaw_audit.sh:45
Finding

Audit artifacts inherit potentially permissive filesystem permissions

Content
View full analysis
"${ROOT}/${name}.txt" } run_cmd() { local name="$1"; shift local file="${ROOT}/${name}.txt" log "Running: $*" { echo "$ $*" "$@" } > "${file}" 2>&1 || { echo "[warn] command failed (continuing): $*" >> "${file}" return 0 } } ``` ### Technical Analysis The collector creates its output directory and files without setting a restrictive `umask` or explicitly applying secure permission modes. Their permissions therefore depend on the invoking process's environment. With a common `umask` of `022`, the directory can be created as mode `0755` and files as mode `0644`, making collected artifacts readable by other local users. The output includes host identity, network listeners, firewall rules, container information, OpenClaw configuration values, plugin and skill inventories, state-directory metadata, and security-audit findings. The script does not intentionally copy credential-file contents, but the collected information remains security-sensitive and may reveal enough deployment detail to support targeted attacks. ### Attack Path 1. An operator runs the collector on a multi-user system with a permissive `umask`, such as `022`. 2. The collector creates the timestamped audit directory and files using inherited default permissions. 3. Another local user enumerates the operator's accessible audit output directory. 4. That user reads the generated `.txt` files. 5. The user obtains information about exposed ports, firewall policy, Gateway configuration, authentication mode, enabled tools, plugins, containers, and known security ...[truncated 931 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (32)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose describes a broad OpenClaw security review and hardening skill. The actual code chunk only implements config redaction: it loads a file or stdin, attempts JSON/JSON5 parsing, masks sensitive keys and secret-looking values, and outputs redacted content. While this is security-adjacent and could support safe sharing during an audit, it is not the declared primary function and introduces an undeclared concrete capability (sanitizing config files). There is no logic for reviewing gateway exposure, auth, access controls, plugins, sandboxing, logs, deployment posture, or interpreting openclaw security audit output. Therefore the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
Audit and discuss these paths carefully without asking for raw contents:

- `~/.openclaw/openclaw.json`
- `~/.openclaw/secrets.json`
- `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
- `~/.openclaw/agents/<agentId>/sessions/*.jsonl`
- `/tmp/openclaw/openclaw-YYYY-MM-DD.log`

YARA rule 'exploit_framework': Exploit framework components and payloads [hacktools]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · assets/report-template.md (reported line 66)May include surrounding context.

md
nnels
- [ ] Gateway is not reachable from untrusted networks
- [ ] DM pairing/allowlists are in place
- [ ] Group mention gating is enabled where required
- [ ] File permissions are tightened for OpenClaw state and config
- [ ] Tools are limited to what is actually required

## Residual risk notes

Even a well-hardened agent that can read messages and call tools still carries prompt-injection and social-engineering risk. Record which surfaces remain intentionally open, which tools remain enabled, and how recovery works if the Gateway host or credentials are compromised.

YARA rule 'exploit_framework': Exploit framework components and payloads [hacktools]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/render_report.py (reported line 494)May include surrounding context.

python
nnels
- [ ] Gateway is not reachable from untrusted networks
- [ ] DM pairing/allowlists are in place
- [ ] Group mention gating is enabled where required
- [ ] File permissions are tightened for OpenClaw state and config
- [ ] Tools are limited to what is actually required

## Residual risk notes

Even a well-hardened agent that can read messages and call tools still carries prompt-injection and social-engineering risk. Record which surfaces remain intentionally open, which tools remain enabled, and how recovery works if the Gateway host or credentials are compromised.

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Code deploys a privileged Kubernetes workload (privileged container, hostPath mount, or host namespaces). This grants root on the node and is a node/cluster takeover vector.

Content

Scanner excerpt · references/platform-docker.md (reported line 34)May include surrounding context.

md
- keep host-side permissions on the mounted state dir restrictive

4. **Container privileges**
   - avoid `privileged: true`
   - avoid `network_mode: host`
   - avoid unnecessary capabilities
   - run as a non-root user where practical

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
- `openclaw security audit --json`
   - `openclaw security audit --deep --json`
4. Treat the **Gateway**, **Control UI**, **browser control**, **paired nodes**, and **automation surfaces** as operator-level access.
5. Default to **audit-only**. Before any config edits, `--fix` operations, firewall changes, or restarts, create a backup first and get explicit user approval.
6. When the user wants remediation, make the backup step explicit:
   - `openclaw backup create --verify`
   - use `--no-include-workspace` if the config is invalid but you still need state + creds

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
- Paired nodes are remote execution surfaces. Audit them like you would audit operator access.
- Browser control is not “just viewing pages”; it is effectively remote operator capability.
- `gateway` / `cron` tools create persistence and should not be reachable from untrusted chat surfaces.

### 7) Secrets, logs, transcripts, and writable paths

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
### 7) Secrets, logs, transcripts, and writable paths

Audit and discuss these paths carefully without asking for raw contents:

- `~/.openclaw/openclaw.json`
- `~/.openclaw/secrets.json`

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · assets/openclaw_checkid_map.json (reported line 2)May include surrounding context.

json
{
  "fs.state_dir.perms_world_writable": {
    "severity": "critical",
    "category": "filesystem",
    "why": "Other users or processes can modify the full OpenClaw state directory.",

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · references/openclaw-audit-checks.md (reported line 9)May include surrounding context.

md
{
  "fs.state_dir.perms_world_writable": {
    "severity": "critical",
    "category": "filesystem",
    "why": "Other users or processes can modify the full OpenClaw state directory.",

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/command-cheatsheet.md (reported line 24)May include surrounding context.

Back up first:

bash
openclaw backup create --verify

If the config is invalid but you still want a safety copy:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/command-cheatsheet.md (reported line 104)May include surrounding context.

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/command-cheatsheet.md (reported line 105)May include surrounding context.

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/command-cheatsheet.md (reported line 106)May include surrounding context.

bash
ss -ltnp
sudo ufw status verbose || true
sudo nft list ruleset || true
sudo iptables -S || true

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · assets/openclaw_checkid_map.json (reported line 16)May include surrounding context.

json
|---|---|---|---|---:|
| `fs.state_dir.perms_world_writable` | Critical | Other users/processes can modify the full OpenClaw state directory. | filesystem perms on `~/.openclaw` | Yes |
| `fs.config.perms_writable` | Critical | Others can change auth, tool policy, and routing config. | perms on `~/.openclaw/openclaw.json` | Yes |
| `fs.config.perms_world_readable` | Critical | The config can leak tokens or security-sensitive settings. | perms on config file | Yes |
| `gateway.bind_no_auth` | Critical | Remote bind without shared secret. | `gateway.bind`, `gateway.auth.*` | No |
| `gateway.loopback_no_auth` | Critical | Reverse-proxied loopback can become unauthenticated. | `gateway.auth.*`, proxy setup | No |
| `gateway.http.no_auth` | Warn/Critical | HTTP endpoints are reachable with `auth.mode="none"`. | `gateway.auth.mode`, `gateway.http.endpoints.*` | No |

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · references/openclaw-audit-checks.md (reported line 11)May include surrounding context.

md
|---|---|---|---|---:|
| `fs.state_dir.perms_world_writable` | Critical | Other users/processes can modify the full OpenClaw state directory. | filesystem perms on `~/.openclaw` | Yes |
| `fs.config.perms_writable` | Critical | Others can change auth, tool policy, and routing config. | perms on `~/.openclaw/openclaw.json` | Yes |
| `fs.config.perms_world_readable` | Critical | The config can leak tokens or security-sensitive settings. | perms on config file | Yes |
| `gateway.bind_no_auth` | Critical | Remote bind without shared secret. | `gateway.bind`, `gateway.auth.*` | No |
| `gateway.loopback_no_auth` | Critical | Reverse-proxied loopback can become unauthenticated. | `gateway.auth.*`, proxy setup | No |
| `gateway.http.no_auth` | Warn/Critical | HTTP endpoints are reachable with `auth.mode="none"`. | `gateway.auth.mode`, `gateway.http.endpoints.*` | No |

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/collect_openclaw_audit.sh (reported line 79)May include surrounding context.

sh
run_cmd_maybe_sudo() {
  local name="$1"; shift
  local file="${ROOT}/${name}.txt"
  if command -v sudo >/dev/null 2>&1; then
    log "Running (sudo -n): $*"
    {
      echo "$ sudo -n $*"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/collect_openclaw_audit.sh (reported line 82)May include surrounding context.

sh
run_cmd_maybe_sudo() {
  local name="$1"; shift
  local file="${ROOT}/${name}.txt"
  if command -v sudo >/dev/null 2>&1; then
    log "Running (sudo -n): $*"
    {
      echo "$ sudo -n $*"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/collect_openclaw_audit.sh (reported line 83)May include surrounding context.

sh
run_cmd_maybe_sudo() {
  local name="$1"; shift
  local file="${ROOT}/${name}.txt"
  if command -v sudo >/dev/null 2>&1; then
    log "Running (sudo -n): $*"
    {
      echo "$ sudo -n $*"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/collect_openclaw_audit.sh (reported line 85)May include surrounding context.

sh
run_cmd_maybe_sudo() {
  local name="$1"; shift
  local file="${ROOT}/${name}.txt"
  if command -v sudo >/dev/null 2>&1; then
    log "Running (sudo -n): $*"
    {
      echo "$ sudo -n $*"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/collect_openclaw_audit.sh (reported line 89)May include surrounding context.

sh
run_cmd_maybe_sudo() {
  local name="$1"; shift
  local file="${ROOT}/${name}.txt"
  if command -v sudo >/dev/null 2>&1; then
    log "Running (sudo -n): $*"
    {
      echo "$ sudo -n $*"

Static analysis

No suspicious patterns detected.