You can ship an OpenClaw agent in 60 seconds, but a security incident lasts forever. This guide documents a hands-on process for auditing third-party or in-house OpenClaw skills before they reach production. Everything here is based on real audits we ran on v3.8.1 of the framework and dozens of skills in the wild.

Why auditing OpenClaw skills matters

OpenClaw agents run under Node 22+, with browser control, shell access, scheduled tasks, and over 800 integrations via Composio. A single malicious skill.js can exfiltrate tokens, fork bomb the host, or spam a Slack workspace faster than you can say “npm audit”. Unlike a classic NPM package, a skill executes in the context of an already-privileged agent that you or your users trust. Treat it more like a browser extension audit than a dependency bump.

Establishing a repeatable audit pipeline

Ad-hoc reviews do not scale. The pipeline below fits in any CI runner (we use GitHub Actions) and surfaces 80 % of issues before a human even looks at code.

  1. Static lint pass (eslint@9, custom OpenClaw rules)
  2. Automated pattern scan (Semgrep, 63 rules we’ll share)
  3. Manual SKILL.md review (red flags in documentation)
  4. Scoped runtime test in --sandbox mode
  5. Outbound traffic diff against “known-good” baseline
  6. Post-merge dynamic scan inside staging agent

The rest of this article walks through each step.

Step 1: Inspect the SKILL.md for red flags

Every skill is required by convention (not by the runtime) to ship a SKILL.md that describes:

  • Purpose and intent
  • Required environment variables / secrets
  • Permissions needed (shell, browser, memory)
  • External services contacted

Things we look for immediately:

  • Over-broad claims. “Needs full disk access” even though it just resizes images.
  • Missing auth flow clarity. If the skill posts to GitHub, does it ask for repo scope or repo, admin:org? The latter is rarely necessary.
  • Opaque update policy. If the author auto-updates via curl | bash, stop reading and reject the PR.

Tip: wire a grep job that fails CI when SKILL.md contains “curl” and “sudo” on the same line.

Step 2: Map every outbound request

Most data leaks hide in HTTP calls. We run a two-phase approach:

Static mapping

A Semgrep rule catches patterns like:

axios.post(/https?:\/\/[^"]+/, ...)

and annotates the file. We dump unique domains into outbound_static.txt for later diff.

Dynamic mapping

Spin up the skill in sandbox:

npx openclaw run --skills ./third_party/image-resize --sandbox

Then monitor network:

mitmproxy --mode transparent --set block_global=false --listen-port 8080

Compare domains observed at runtime (outbound_dynamic.txt) with the static set. Any delta needs human eyes.

Edge case: skills that rely on websocket or gRPC. Add tcpdump capture to pick those up:

sudo tcpdump -i any -w skill.pcap host not 127.0.0.1

Step 3: Verify file system and shell scope

OpenClaw exposes a helper in the agent context:

ctx.exec("ls -la /home/openclaw")

This is powerful and abusable. Questions we ask:

  • Does the skill write outside ctx.paths.temp?
  • Does it read user memory (hosted under ~/.openclaw/memory) without explicit intent?
  • Does it spawn nested shells (/bin/sh -c inside Bash)? That often indicates obfuscation.

Simple grep:

grep -R "exec(" third_party/image-resize | grep -v "ctx.exec('convert'"

CI fails on hits.

If the skill needs shell for legitimate image processing, we pin to a whitelist:

"allowedCommands": ["convert", "identify"]

and load a patched runtime guard:

OPENCLAW_ALLOWED_CMDS=$(cat allowed.json) npx openclaw run --sandbox

Step 4: Contain the skill in sandbox mode first

OpenClaw v3.7 introduced --sandbox. Under the hood it spawns the skill in a child process with:

  • Read-only FS except /tmp/openclaw-sandbox-*
  • Network egress blocked except domains defined in skill.json
  • No access to persistent memory

Enabling it is one flag:

npx openclaw run --skills ./third_party/image-resize --sandbox

Watch for runtime errors. If the skill crashes because it cannot write to /home/openclaw, that’s a bug in the skill, not the sandbox. Fix or reject.

We keep sandbox mode enabled in production for 90 % of skills. The 10 % outliers are typically internal DevOps helpers that need shell access.

Step 5: Automate with static and dynamic scanners

Static scan: Semgrep

Create .semgrep/openclaw.yml:

rules: - id: no-hardcoded-keys patterns: - pattern: "${KEY}" message: "Hard-coded key found" severity: ERROR - id: dangerous-child-process patterns: - pattern: child_process.exec($CMD) message: "Unvetted exec call" severity: WARNING

Run in CI:

semgrep --config=.semgrep --json | tee semgrep.json

Fail the build on any ERROR.

Dynamic scan: OClawSec

The community published a small wrapper “OClawSec” (MIT license) that pipes the agent through node --inspect, watches syscalls, and generates a SARIF report. Install:

npm i -g oclawsec

Then:

oclawsec scan --skill ./third_party/image-resize --timeout 120

Common findings:

  • Temp file not deleted after run
  • Unexpected DNS lookup (geo.ipify.org used for tracking)
  • Telemetry pings back to author’s server

Step 6: Document, patch, and upstream fixes

Auditing without remediation is just academic. We follow GitHub’s security advisory flow:

  1. Open SECURITY.md issue in private fork, include PoC and logs
  2. Offer patch PR, require maintainer sign-off
  3. Release patched version tagged vX.Y.Z-secure
  4. Archive CVE via GitHub Advisory Database if severity >= 7.0 CVSS

For internal skills, the checklist lives in a Notion page linked from each repo. Failures block deploy in ClawCloud via our Slackbot (/claw approve deploy-43 rejects if audit-status ≠ “pass”).

Checklist: questions to ask before deploying to production

  • Does SKILL.md list every environment variable it reads?
  • Did static scan find any hard-coded secrets?
  • Do dynamic network logs match the doc?
  • Is sandbox mode enabled in production?
  • Are shell commands whitelisted?
  • Have we fuzz-tested inputs for command injection?
  • Is the skill pinned to a commit hash, not main?
  • Do we have alerts for abnormal memory or CPU spikes?

If the answer to any question is “no”, the deploy waits.

Resources and next steps

  • OpenClaw Security Guide v3.8.1 (docs folder in the repo)
  • Sample Semgrep ruleset: github.com/clawcloud/sec-rules
  • oclawsec dynamic scanner: npmjs.com/package/oclawsec
  • Community thread: “How we sandboxed 150 skills” (#4287)

Auditing is never “done”, but the process above compresses it into a checklist that fits any engineering sprint. Wire it into CI today, enable --sandbox by default, and ship skills without losing sleep.