Browse guides
Back to Guides
IntermediateSecurity & HardeningOpenClaw

How to audit a SKILL.md: OpenClaw skill security checks before and after install

SKILL.md security checks end to end: what to read in a skill's SKILL.md, how to read ClawHub's scan state and audit status, and what to verify after install.

Mira Castellan25 minutes

Auditing one skill is five passes over two artifacts: the skill's own SKILL.md, and ClawHub's stored opinion of the release it came from. Read the file and its declarations, read the scan state and audit status, work out which tools the body would reach for, decide where its credentials live, then re-check your own deployment after the install. Nothing in the toolchain does that first pass for you, which is why OpenClaw's skills reference says to treat third-party skills as "untrusted code" and to "Read them before enabling." Every command, field and label below was checked against v2026.9.5, the latest release listed in the OpenClaw docs as of September 19, 2026.

#What does a skill audit cover?

Five surfaces, and the last one is about your deployment rather than the skill.

The text and its declarations. A skill is a Markdown file: the skills reference calls skills "markdown instruction files that teach the agent how and when to use tools", and the creating-skills page splits the file in two, where "The frontmatter defines metadata; the body gives the agent instructions." The audit question is whether those two halves agree.

ClawHub's stored opinion. The registry publishes a scan state, an audit status and a risk level for the release, and openclaw skills verify reads that decision rather than analysing the bundle on your machine.

The runtime gating. metadata.openclaw decides whether the agent can see the skill, not what it may do. The skills reference draws that line in one clause: "an eligible skill does not grant tool access."

The credentials in reach. What the frontmatter declares, where the value is stored, and which hosts that value may be sent to.

Your own deployment. The agent that will run the skill, and the tool and sandbox policy bounding it.

Each check reads a different artifact and has a different blind spot.

CheckWhat it readsWhat it cannot tell you
clawhub inspect @owner/<slug> --file SKILL.mdThe published file. The command "Fetches skill metadata and version files without installing."Whether the body and the declarations agree. That reading is yours
openclaw skills verify @owner/<slug> --cardClawHub's stored decision. verify "reads the stored scan and does not start another scan"Anything that changed after that scan ran
The skill page's security auditClawHub's published result: the overall audit status, the risk level and any listed findingsThat the release is safe. Audits "are not a guarantee that a release is risk-free"
openclaw skills checkLocal readiness. It "reports missing prerequisites independently of agent exclusion"What the instructions in the body actually ask the agent to do
openclaw security auditYour deployment. It "stays on the cold config/filesystem/read-only path"Anything inside the skill bundle

There is no per-skill capability list to audit. The documented frontmatter gates eligibility through metadata.openclaw, and the tool permissions page states the containment rule for the folder itself: "Treat skill folders as trusted code and restrict who can modify them." What the skill can reach is decided by the agent that runs it.

#Step 1: Read the SKILL.md

Read it before you install it. ClawHub's CLI reads a published file without installing it: inspect "Fetches skill metadata and version files without installing.", --files will "list files for the selected version", and --file <path> will "fetch raw file bytes (10MB limit)".

bash
npm i -g clawhub
clawhub inspect @owner/<slug> --files
clawhub inspect @owner/<slug> --file SKILL.md

Then work the file top to bottom.

  1. The description against the body. description is "One-line description shown to the agent and in discovery output", and eligible skills are "compiled into a compact XML block and injected into the system prompt", so that single line is what the model matches on before it opens anything. A description narrower than the body is the finding, not a style problem.

  2. requires.*, os and always. requires.bins means "Each binary must exist on PATH.", requires.env means "Each env var must exist in the process or be provided via config.", requires.config means each openclaw.json path "must be truthy", and os is a "Hard platform filter." Read them as a description of what the skill expects to find on your host, and note that always switches the checks off: it includes the skill "whenever its os requirement is compatible, bypassing requires.bins, requires.anyBins, requires.env, and requires.config." An absent block is the permissive case, because "A skill with no metadata.openclaw block is always eligible unless explicitly disabled."

  3. primaryEnv and envVars against the credentials the body uses. primaryEnv is the "Env var name associated with skills.entries.<name>.apiKey.", and envVars holds "Environment variable declarations with name, optional required, and optional description." ClawHub's skill format page also tells publishers not to pad the hard gate, saying "Do not add optional entries to requires.env, because requires.env means the skill cannot run without them." Every credential the body reaches for should appear in one of those three places.

  4. user-invocable and disable-model-invocation. The first, when true, means "the skill is exposed as a user-invocable slash command." The second, when true, means "OpenClaw keeps the skill's instructions out of the agent's normal prompt", and the skills reference is precise about the consequence: an authorized explicit $skill-name reference still invokes it, because "the flag only hides the skill from model-initiated selection." Neither is malicious on its own. Both change who decides to run the skill, so note which path this skill expects.

  5. command-dispatch and command-tool. When command-dispatch is set to tool, "the slash command bypasses the model and dispatches directly to a registered tool", and command-tool is the "Tool name to invoke when command-dispatch: tool is set." Read that tool name, because it is the one place in the file that names a concrete capability. With the default command-arg-mode, tool dispatch "forwards the raw args string to the tool with no core parsing."

  6. install and nix. install holds "Optional installer specs used by the macOS Skills UI (brew / node / go / uv / download).", and ClawHub's field reference lists nix as a "Nix plugin spec (see README)." A download spec is the one to read closely, because its integrity check is optional: the skills reference documents sha256 as an optional 64-character hexadecimal digest, "verified after download and before the file is installed or extracted", and adds that "Existing specs without sha256 keep the previous download behavior." A download installer with no digest fetches an artifact whose contents are not pinned.

  7. Every file the body references. The creating-skills page shows how a body points at its own folder, letting an author "Reference files inside the skill directory without hardcoding paths", where "the agent resolves {baseDir} against the skill's own directory". A SKILL.md that reads cleanly can still hand the agent a script you have not read, so list the bundle with --files and read what the body points at.

A body that reaches for something the frontmatter never names is a finding on ClawHub's side too. Its skill format page says "ClawHub's security analysis checks that what your skill declares matches what it actually does", and that when the body references a variable the frontmatter does not declare under requires.env, primaryEnv or envVars, "the analysis will flag a metadata mismatch". The Security Audits page frames the whole review the same way: "The main question is coherence: do the name, summary, metadata, requested authority, and actual content line up with what users would reasonably expect?"

#Step 2: Check the ClawHub scan state and audit status

Now ask the registry what it already decided.

bash
openclaw skills verify @owner/<slug>
openclaw skills verify @owner/<slug> --card

The plain form "Prints ClawHub's clawhub.skill.verify.v1 JSON envelope by default." The --card form "Prints the generated Skill Card Markdown instead of JSON." and "Exits non-zero when ClawHub returns ok: false" or a fail decision, which is the behaviour to wire into a script. The skills reference states the same rule for the underlying check: "The command exits non-zero when ClawHub marks verification as failed." For a skill you already installed, verify "uses .clawhub/origin.json for installed ClawHub skills, so it verifies the installed version against the registry it came from."

Read the listing as well. The skills reference says "ClawHub skill pages expose the latest security scan state before install", and the Security Audits page lists what to review before installing: the overall audit status, the risk level, any listed findings, "required credentials, permissions, or environment variables", and the "owner, source, version, changelog, downloads, stars, and other trust signals".

The two published labels answer different questions. Audit status asks "What should I do with this result?" and runs Pass ("No visible issue above low risk was found."), Review ("Read the findings before installing. The release may still be legitimate."), Warn ("Use extra caution. ClawHub found a high-impact concern or warning signal.") and Malicious ("Do not install."), plus two states rather than verdicts, Pending ("Audits have not finished yet.") and Error ("The audit could not be completed."). Risk level asks "How much power is here?" across Low, Medium and High, and the page defines it as blast radius, "how much power the release appears to have if you use it as intended." A Review result at Medium risk is the page's own example of a legitimate publishing skill, not an accusation.

Findings are the evidence under those labels. They "may be labeled Info, Low, Medium, High, or Critical", and you are not seeing all of them: "Low-confidence findings are hidden from the public audit rollup so the page stays focused on useful evidence."

Three named components feed the audit page, which lives at /<owner>/skills/<slug>/security-audit and combines SkillSpector, A.I.G and risk analysis. "Skill audits include findings from Tencent Zhuque Lab's A.I.G scanner", which checks agent instructions for vulnerability patterns, and the page is explicit that "It does not issue ClawHub's final verdict or independently block installation." A.I.G's evidence feeds the third component, which is ClawHub's own system: "Risk analysis is powered internally by ClawScan, ClawHub's own security audit system." ClawScan reads the release using the OWASP Agentic Skills Top 10 "as a lens for risks such as prompt injection, tool misuse, credential exposure, unsafe execution, memory or context poisoning, and excessive agency." Static scan signals feed that review rather than standing on their own: they "are not a standalone public audit section or install-blocking verdict."

Two other states change what you should do.

Unscanned sources. External skills-sh: listings are shown as "Not scanned by ClawHub", and the skills CLI page says "that trust state is preserved through updates and verification." Installing a pending GitHub-backed release ahead of its scan is a deliberate flag, --force-install, which "Installs a pending GitHub-backed ClawHub skill before ClawHub's scan completes." Release trust otherwise runs before download, where "Malicious or blocked community releases are refused", and "Review outcomes print the exact ClawHub audit overview and details link, then continue." Two sources sit outside that gate entirely: "Official ClawHub skill publishers and bundled OpenClaw skill sources bypass this release-trust check."

Moderated listings. A release can be "held, hidden, quarantined, revoked, or otherwise unavailable on public install surfaces", and the moderation page's instruction is unambiguous: "If you see one of these states, do not install the release unless the owner resolves the issue or moderation restores it."

The underlying report files exist, but reaching them is a publisher's privilege rather than a reader's. clawhub scan says "Published scans require ownership or publisher management access.", and its --output <file.zip> "downloads the full report archive with manifest.json, clawscan.json, skillspector.json, static-analysis.json, virustotal.json, and README.md."

#Step 3: Inspect what it would run

A skill has no execution of its own. Its body is text the model reads and acts on, which is why the docs' own starter skill tells the agent to "use the exec tool to run" a command. The practical question is which tools the body names, and whether the agent that will read it can call them.

Take the tool names out of the body, then look at the agent. openclaw sandbox explain "inspects effective sandbox mode, host workspace, runtime workdir, Docker mounts, tool policy, and fix-it config keys", which is the documented way to see the policy the skill will actually meet.

bash
openclaw sandbox explain --agent <id>

Three documented layers decide the answer.

Tool policy. It runs first and it wins: "Tool allow/deny policies still apply before sandbox rules. If a tool is denied globally or per-agent, sandboxing doesn't bring it back." For an agent handling untrusted content, the tool permissions page recommends denying gateway, cron, sessions_spawn and sessions_send by default, and the prompt injection page adds the high-blast-radius set: "Limit high-risk tools (exec, browser, web_fetch, web_search) to trusted agents or explicit allowlists."

Sandboxing. "OpenClaw can run tool execution inside a sandbox backend to reduce blast radius." It is not on until you turn it on, since "Sandboxing is off by default", and what the sandbox can see of your files is one setting: the default "none" means "tools see a sandbox workspace under ~/.openclaw/sandboxes; agent workspace is off-limits", "ro" "mounts the agent workspace read-only at /agent", and "rw" "mounts the agent workspace read/write at /workspace". One hole is documented by name: tools.elevated "is an explicit escape hatch that runs exec outside the sandbox".

Exec policy. If the body drives a shell, the interpreter rules matter. When interpreters are allowlisted, the prompt injection page says to "enable tools.exec.strictInlineEval so inline eval forms (-c, -e, and similar) still need explicit approval", and that in allowlist mode "any heredoc segment (<<) always requires reviewer or explicit approval, regardless of quoting". The creating-skills page puts the authoring side of the same point as a rule for skills that shell out: "if your skill uses exec, ensure prompts do not allow arbitrary command injection from untrusted input."

Egress is bounded per secret rather than per skill, and it fails shut: "Secret egress substitution fails closed until each secret has at least one exact allowed host." The host list is exact by design, since "Schemes, paths, ports, and wildcards are rejected."

#Step 4: Decide where its credentials live

The frontmatter names a variable. You decide what the value is and who can read it.

The binding runs from the skill into config: primaryEnv is the "Env var name associated with skills.entries.<name>.apiKey.", and apiKey is a "Convenience field for skills that declare metadata.openclaw.primaryEnv." that "Supports a plaintext string or a SecretRef object." Use the SecretRef. A literal in config, and far worse a literal in the body, is a value the agent can read back, which is why the skills reference states the rule for the file itself in one line: "Keep credentials out of skill content."

Store the value through the secrets CLI, which is built so the credential never lands in shell history.

bash
openclaw secrets store set WEATHER_API_KEY --kind secret
openclaw secrets store set WEATHER_API_KEY --allow-host api.example.com
openclaw secrets reload

Three input rules matter during an audit. First, --value "is accepted only when the resolved kind is env", and "For secret values, --value is refused with exit code 2 because command-line arguments can leak through shell history and process listings." The three accepted inputs are to "Pipe stdin when stdin is not a TTY.", to "Pass --value-file <path>. --value-file - means stdin.", or to "Run interactively and enter the value in the no-echo prompt." Second, the kind is inferred from the name unless you set it, since names ending in a common credential suffix such as "_API_KEY, _TOKEN, _PASSWORD, _PRIVATE_KEY, or _SECRET become secret, and other names become env." Third, stored secrets stay write-only: "Secret values never appear in human, --json, or --plain output."

The kind is the boundary that decides what a skill's commands can see. "Team-scoped env entries reach Gateway-hosted commands run by OpenClaw's own exec tool", while "secret entries stay out of subprocesses by default." Anything credential-shaped belongs to secret.

Two caveats close the step. A stored value does not reach a container: "Inside a sandbox, env and apiKey have no effect." And a write is not live until you reload, because a successful write "reminds you to run openclaw secrets reload before a config-referenced value can take effect." The skills reference adds the standing rule for everything else: "Keep secrets out of prompts and logs."

API key setup covers the provider side, including the SecretRef sources OpenClaw accepts and how to revoke a key that leaked.

#Step 5: Install, then verify the host

Install with the owner-qualified form, and know which directory you are writing into.

bash
openclaw skills install @owner/<slug>
openclaw skills install @owner/<slug> --global

The skills CLI states the boundary once for the whole family: "By default, install, update, and verify target the active workspace skills/ directory; with --global, they target the shared managed skills directory." The workspace form is the narrower audit choice, because --global installs into the shared ~/.openclaw/skills directory, "visible to all local agents unless agent allowlists narrow it."

Then confirm what actually loaded.

bash
openclaw skills check
openclaw skills check --agent <id>
openclaw skills info <name>

check is the readiness report, and it "reports missing prerequisites independently of agent exclusion", so a skill whose declared binary or environment variable is missing appears under missing requirements instead of quietly dropping out of the prompt. With an agent id it goes further and "Checks the selected agent's workspace and reports which ready skills are actually visible to that agent's prompt or command surface." That is the line that tells you whether the thing you just audited is in front of the agent you meant. info then reads one skill back by the name you audited, since "info resolves an exact skill name before a metadata key."

Finally, audit the deployment rather than the bundle.

bash
openclaw security audit
openclaw security audit --deep
openclaw security audit --json | jq '.summary'

The two forms differ in coverage, not severity. "Plain security audit stays on the cold config/filesystem/read-only path: it does not discover plugin runtime security collectors, so routine audits do not load every installed plugin runtime", while "--deep adds best-effort live Gateway probes and plugin-owned security audit collectors". No documented check in either form reads the skill bundle. The documented checks are all deployment surface: the DM and trust model, webhooks and hooks, sandbox and tool settings, the sandbox browser, network and discovery, plugins and channels, and dangerous flags. That is still the right thing to run after an install, because the widening a bad skill talks you into is exactly what those checks catch.

Read the result before acting on --fix. The fix pass "Applies safe, deterministic remediations" such as tightening permissions on state and config files, and the page lists what it leaves alone: it does not "rotate tokens/passwords/API keys", does not disable tools, does not change gateway bind, auth or network exposure choices, and does not "remove or rewrite plugins/skills".

Re-run openclaw skills verify @owner/<slug> --card after every update. An update without --force leaves your edits in place, since "Without it, updates preserve local changes.", but the release you now have is not the release you audited. A new version means a new stored decision to read.

If the skill has to come off, removal runs through the standalone ClawHub CLI from the workdir it was installed into, and every credential it declared should be treated as readable by the run it already had. Skill security has the removal, rotation and log-reading sequence in full.

#What does an audit not tell you?

Four limits, stated where the docs state them.

A listing is not a verdict on your deployment. ClawHub's Security Audits page says audits "are not a guarantee that a release is risk-free", and ends its pre-install checklist with "Install only content you understand and trust." Publishing validates metadata, not intent: ClawHub "validates the metadata, name, version, files, and source information, then stores the release and starts automated security checks", and "If validation fails, nothing is published."

A scan state is a point in time. verify "reads the stored scan and does not start another scan", so it reports a decision ClawHub already reached. Local integrity is not what it checks either: OpenClaw "treats verification as a ClawHub server decision and does not reject an installed skill just because that generated card changes the bundle fingerprint." Scanner coverage is versioned, and the docs name one bound together with its mitigation: "A.I.G 0.2.1 cannot inspect packaged Python bytecode", so for now "ClawHub rejects skills containing .pyc, .pyo, or .pyd files before A.I.G runs" and "ClawScan also detects packaged Python bytecode independently."

No audit of a file covers what the agent reads later. The prompt injection page is blunt about where the risk sits: any untrusted content the agent reads, from fetched pages to emails to pasted logs, can carry adversarial instructions, and "The content itself is a threat surface, not just the sender." Its working rule applies to a skill's own references as much as to the open web: "Treat links, attachments, and pasted instructions as hostile by default."

The trust model is per gateway, not per skill. OpenClaw supports "one trust boundary per gateway", and "Everyone who can message a tool-enabled agent shares that agent's delegated tool authority." The trust model page also closes "Prompt-injection-only chains without a policy, auth, or sandbox bypass." as no-action, which tells you where the enforceable boundary is: tool policy, auth and the sandbox, not the wording of a Markdown file.

  • Skill security covers the surrounding system: what a skill can reach, the containment controls, keeping installs current, and what to do after a bad one.
  • Building custom skills is the authoring side of the same schema, with every documented metadata.openclaw field and where a SKILL.md loads from.
  • API key setup covers provider credentials, the SecretRef sources OpenClaw accepts, and revoking a key that leaked.

Every command, field and label on this page was checked against the OpenClaw and ClawHub documentation on September 19, 2026. Re-read the sources below before copying a command out of any tutorial, including this one.

Frequently asked questions

What should you read first in a skill's SKILL.md?
The description, then the body, then the two against each other. OpenClaw's creating-skills reference calls description a one-line description shown to the agent and in discovery output, and the skills reference says eligible skills are compiled into a compact XML block and injected into the system prompt. The agent picks the skill from that line before it ever opens the body, so a narrow description over a broad body is the mismatch worth finding.
What does openclaw skills verify tell you?
ClawHub's stored decision about that release, not a fresh analysis of the files. The skills CLI page says verify prints ClawHub's clawhub.skill.verify.v1 JSON envelope by default, that --card prints the generated Skill Card Markdown instead of JSON and exits non-zero when ClawHub returns ok: false, and that verify reads the stored scan and does not start another scan.
What does a ClawHub audit status mean?
It tells you how to react to the audit result. ClawHub's Security Audits page defines Pass as no visible issue above low risk was found, Review as read the findings before installing, Warn as use extra caution, and Malicious as do not install. Pending and Error are states rather than verdicts: audits have not finished yet, or the audit could not be completed.
What should you do if a skill's body uses an environment variable it never declares?
Treat it as the skill's real requirements not being on the label. ClawHub's skill format page says its security analysis checks that what your skill declares matches what it actually does, and that a variable referenced in the body but absent from requires.env, primaryEnv or envVars will flag a metadata mismatch. Ask the publisher, or do not install until the declaration is fixed.
Does a ClawHub listing mean a skill is safe?
No. ClawHub's Security Audits page says audits are strong safety signals, but they are not a guarantee that a release is risk-free, and closes its pre-install checklist with install only content you understand and trust. A listing can also be held, hidden or quarantined later, and the moderation page says not to install a release in one of those states.
Can openclaw security audit check a skill?
No, it audits your deployment instead. The security CLI page documents openclaw security audit and openclaw security audit --deep, and its documented checks cover the trust model, hooks, sandbox and tool settings, the sandbox browser, network and discovery, plugins and channels, and dangerous flags. Run it after installing a skill to see whether the install talked you into widening anything.

Sources

  1. OpenClaw: Skills
  2. OpenClaw: Creating skills
  3. OpenClaw: Skills CLI
  4. OpenClaw: Security CLI
  5. OpenClaw: Secrets CLI
  6. OpenClaw: Tool and agent permissions
  7. OpenClaw: Prompt injection
  8. OpenClaw: Security trust model
  9. OpenClaw: Sandboxing
  10. OpenClaw: Release notes
  11. ClawHub: CLI
  12. ClawHub: Skill format
  13. ClawHub: Security Audits
  14. ClawHub: Moderation and Account Safety
  15. ClawHub: Publishing

Skip the trial and error

ClawDocx members get 500+ tested prompts, ready-to-install SKILL.md files, SOUL.md and CLAUDE.md templates, and an MCP server so your agent can pull all of it directly while it works.