Most OpenClaw agents get their superpowers from third-party skills. The trade-off is obvious: every extra line of unvetted JavaScript now runs with the same authority as your agent, your Slack token, maybe even process.env.OPENAI_API_KEY. Last quarter Cisco Talos researchers caught a credential-harvesting skill masquerading as a “Google Drive summarizer”. Nobody wants to be the next headline.
Why Skill Security Matters (Ask Cisco Talos)
In August 2024 Cisco’s security team reverse-engineered twenty community skills. One, openclaw-gdocs-helper, quietly POSTed conversation transcripts to paste[.]audit-log[.]xyz. Less than 100 lines of obfuscated code siphoned private Slack DMs and OpenAI prompts. The author used a disposable GitHub account and got 97 stars before anyone noticed.
That incident forced us—and frankly the whole OpenClaw community—to admit our marketplace is closer to npm circa 2017 than Apple’s App Store. There is no mandatory review queue, no reproducible build system, no automated signing. You are the last line of defense. This guide shows how to audit a skill before the inevitable claw skill install.
Reading SKILL.md Like a Threat Model
Every skill is supposed to ship a top-level SKILL.md. Don’t skim it; treat it like you’d treat a new Terraform module headed for production.
Quick sanity checklist
- Author identity: GitHub profile with real activity? LinkedIn or company domain? Disposable handles are a red flag.
- Version tags: Look for semantic versions and release notes. Skills stuck at
0.0.1for six months often break silently. - Changelog detail: Does the maintainer log security-relevant changes like scope narrowing or dependency bumps?
- Dependencies:
npm itree should be short. A summarizer does not needpuppeteeroraws-sdk. - Permissions declared: Good skills list required environment variables and external APIs upfront.
- Telemetry: Opt-in analytics are fine. Hard-coded calls to
amplitude.comin the code but absent from docs are not.
Red flags inside the markdown
Search for vague language:
- “may send usage data” → ask what data and where
- “requires admin OAuth scope” → why does a calendar reader need repo:write?
- No LICENSE section → unknown legal status; harder to fork and patch if urgent
Bottom line: if the docs are sloppy, the code probably is too.
Static Scanning: VirusTotal, npm audit, and Your Own Grep
The ClawCloud CLI (>= 1.9.0) integrates with VirusTotal. Turn it on once; every subsequent claw skill install uploads the tarball hash and checks for known IOCs.
claw config set security.virustotal true
# verify
claw config get security
What the setting does:
- Computes SHA-256 of the exact zip served by the registry.
- Hits VirusTotal’s database with an
/file/report?apikey=<org-scoped-token>. - Blocks install if any engine (Dr.Web, Fortinet, etc.) flags it as malicious.
Limitations: VirusTotal only knows what others already caught. Zero-day backdoors sail right through.
Local static checks
I still run:
# inside a temp container
npm ci --ignore-scripts
npm audit --omit=dev
Plus a personal favorite: grepping for network calls outside allowed domains.
grep -R "http[s]*://" . | grep -vE "(api.openai.com|graph.microsoft.com)"
You’ll be amazed how many “simple” skills ship an auto-updater that pings a random S3 bucket every hour.
Sandboxing Untrusted Skills
Node 22 finally gave us experimental permission flags (--allow-fs-read, --allow-net). The OpenClaw daemon exposes those via claw skill sandbox.
# deny everything, then allow net access only to slack.com
claw skill sandbox pdf-reader \
--deny-all \
--allow-net=slack.com
Under the hood the daemon spawns each skill in its own Worker using node --experimental-permission. It’s not bullet-proof—core modules can still abuse child_process—but it shuts the door on casual data leaks.
Docker for the Paranoid (or Regulated)
If you deploy on your own metal instead of ClawCloud SaaS, wrap the entire agent in a minimal Docker image. Run skills with:
--network=none --read-only --cap-drop=ALL
and mount only the sockets you actually need, e.g. /run/user/1000/claw.sock. Yes, this is slower. Yes, it keeps compliance happy.
Reviewing the permissions.json Manifest
Since Gateway v0.18 every skill can (optionally) declare a permissions.json next to package.json. The spec is blunt:
{
"fs": ["read:/tmp/cache"],
"net": ["https://api.github.com", "smtp://mail.example.com:587"],
"env": ["OPENAI_API_KEY"],
"shell": false
}
If the file is missing, the daemon currently defaults to all permissions. That’s a debate on GitHub #982 and hopefully changes soon. Meanwhile you can require an explicit manifest via:
claw config set security.requirePermissionManifest true
Expect skill authors to screw this up. I’ve seen manifests that whitelist net: ["*"] because the author thought it meant “all HTTPs domains are okay”. That defeats the purpose. Push a PR or file an issue; most maintainers will fix it when nudged.
Mapping permissions to risk
- fs write » potential ransomware behavior, especially if path is
/ - net * » data exfiltration, cryptojacking
- env ALL » credential leaks; force a subset
- shell true » remote-code heaven for an attacker
Be ruthless. If a PDF parser wants shell:true, walk away.
The Community Vetting Process (Spoiler: It’s Mostly You)
The harsh truth: there is no formal OpenClaw review board. The #skills Discord channel plus a handful of Github Actions tests are all we have. That said, a few community norms reduce risk:
- Signed tags: Many top skills push GPG-signed git tags. If the latest tag suddenly isn’t signed, hold off.
- PR reviewers: Skills with ≥ 2 mandatory reviewers catch most obvious shenanigans. Look at branch protection rules.
- Reverse bounty channel: Maintainers sometimes post PayPal bounties for anyone who finds security flaws.
But again, none of this is enforced. The marketplace currently lists ~1,300 skills; maybe 150 get regular eyes on them. Until a foundation grows up around OpenClaw, you cannot outsource due diligence.
Hardening Checklist Before claw skill install
- Read
SKILL.md; verify author, scopes, dependencies. - Static scan:
claw --virustotal,npm audit, grep network calls. - Require
permissions.json; refuse if missing. - Sandbox with Node permission flags or Docker.
- Use env vars scoped to the skill, not global secrets.
- Monitor outbound traffic from the daemon (
nethogs,iptables --log). - Pin version numbers; no
^in yourskill.json. - Subscribe to the GitHub repository’s security advisories.
- Consider self-hosting Sentry to catch unexpected exceptions fast.
Yes, it’s work. But so are incident response write-ups and customer apology emails.
Next Step: Automate the Boring Parts
Start by dropping this into your CI pipeline. It blocks pull requests that bump any skill without passing the checks described above.
# .github/workflows/skill-audit.yml
name: Skill Audit
on:
pull_request:
paths:
- "skills/**"
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ClawCloud CLI
run: npm i -g @clawcloud/cli@1.9.0
- name: Run VirusTotal scan
run: claw skill audit --all --virustotal
- name: Check permission manifests
run: claw skill audit --require-permissions
Merge blocks are annoying until the day they save you from shipping a keylogger. Set it up once and forget it.
That’s it. Your agent can keep learning new tricks without leaking your entire Slack history to some burner domain. Stay paranoid and happy hacking.