Back to skill

Security audit

OpenClaw Update Runbook

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent OpenClaw update runbook, but parts of its troubleshooting guidance can expose live channel tokens in terminal or agent transcripts.

Review before installing. Use it only for explicit OpenClaw maintenance tasks, require confirmation before updates/restarts/config edits, and do not run token-inspection commands that print raw values. If a token has already appeared in a transcript, support ticket, log, or backup, rotate it and remove plaintext fallbacks after recovery.

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
references/failure-patterns.md:482
Finding

Authentication Tokens Can Be Printed and Disclosed Through Support Artifacts

Content
View full analysis
"; const l=fs.readFileSync(p,"utf8").split("\n").find(l=>l.startsWith("export =")); console.log(JSON.stringify(l))' ``` - a clean line has a single shell-quoted token value with no inner literal double quotes - a corrupted line has literal `"` characters just inside the shell quotes - check every `*_TOKEN` / `*_API_KEY` line in the env file the same way; the same writer emits all of them Recovery: - back up the env file: `cp .bak-token-fix-` - rewrite the affected lines using the value from `secrets.json` (which is the canonical clean value), shell-single-quoted with no inner JSON wrapping; only safe if the secret itself contains no single quotes (almost always the case for API tokens) - restart the gateway through the host service manager - re-run `openclaw channels status --deep` and confirm the channel reconnects Why it matters: - this is a packaging defect in the env-file writer, not operator drift; the local fix is fragile because the next regeneration will re-corrupt the file - share upstream or with support: exact line bytes, the source `secrets.json` value type (string), and the affected host version ``` A related command directly prints the configured Discord token: ```text - To disambiguate, inspect the actual config field directly: - `node -e 'const c=JSON.parse(require("fs").readFileSync(process.env.HOME+"/.openclaw/openclaw.json","utf8")); console.log(typeof c.channels?.discord?.token, c.channels?.discord?.token)'` ``` ### Technical Analysis ...[truncated 2630 chars]
Remediation
View remediation
' outer shell quotes: present inner literal double quotes: present source value type: string ``` 5. Add an explicit warning that command output generated by older versions of the runbook may contain live credentials and must not be uploaded or pasted into reports. 6. If a token has already appeared in an Agent transcript, terminal recording, support ticket, or other external artifact: - Revoke and rotate it. - Remove the artifact where possible. - Review channel or API logs for unauthorized use. - Update the sanitized handoff notes with the rotation time, but not the replacement value. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/failure-patterns.md:200
Finding

Runbook Recommends Persisting Channel Tokens in Plaintext Configuration

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (16)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
ngle file. It expects `references/failure-patterns.md` to exist locally beside `SKILL.md` inside the same skill bundle.

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

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

md
- cron/session isolation and channel-lane ownership
- runtime performance
- command-path and update-channel assumptions
- self-update hazards when an agent updates the gateway that is running it
- supply-chain and package-integrity spot checks after plugin/npm churn

## Quick workflow

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · references/failure-patterns.md (reported line 750)May include surrounding context.

md
- cron/session isolation and channel-lane ownership
- runtime performance
- command-path and update-channel assumptions
- self-update hazards when an agent updates the gateway that is running it
- supply-chain and package-integrity spot checks after plugin/npm churn

## Quick workflow

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The runbook explicitly recommends a workaround that inlines a literal channel token into config when SecretRef resolution is broken. That weakens secret handling by moving credentials from a managed secrets store into plaintext configuration, increasing exposure through config files, backups, logs, and support artifacts.

Content

Scanner excerpt · references/failure-patterns.md (reported line 224)May include surrounding context.

md
- this can leave a channel integration down after an update even though the secret exists

Confirmed regression scope:
- Reproduced cleanly across multiple adjacent channel-plugin versions with a SecretRef pointing at a valid `secrets.json` entry.
- `openclaw secrets audit` reports `unresolved=0`, `openclaw secrets reload` says "Secrets reloaded.", but the channel plugin still throws `unresolved SecretRef ... Resolve this command against an active gateway runtime snapshot before reading it.` at startup.
- Sibling plugins using the same SecretRef shape (e.g. brave's `/brave_api_key`) resolve fine — the bug is plugin-side, not in the secrets layer.
- Pragmatic workaround (when env fallback isn't available): inline the literal token into the affected channel token field. This adds one entry to `secrets audit --plaintext` findings but restores the channel. Plan to revert once upstream `@openclaw/discord` ships a fix that resolves SecretRefs against the runtime snapshot.

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 · references/failure-patterns.md (reported line 472)May include surrounding context.

md
Symptom:
- a previously working channel returns auth failure from the upstream API immediately after a host upgrade, even though `channels status` reports `token:env` and the channel was healthy before the upgrade
- `secrets audit` reports `unresolved=0` and the underlying value in `secrets.json` is unchanged
- the channel reconnects fine if you manually re-paste the token into the env file

Root cause:

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 · references/failure-patterns.md (reported line 498)May include surrounding context.

md
Symptom:
- a previously working channel returns auth failure from the upstream API immediately after a host upgrade, even though `channels status` reports `token:env` and the channel was healthy before the upgrade
- `secrets audit` reports `unresolved=0` and the underlying value in `secrets.json` is unchanged
- the channel reconnects fine if you manually re-paste the token into the env file

Root cause:

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The runbook explains how secrets are written into a service env file and shows the exact malformed export shape containing the token value. Even though framed as debugging guidance, it normalizes direct handling of credential material in env files and risks accidental disclosure if operators copy raw lines into tickets, chats, or logs.

Content

Scanner excerpt · references/failure-patterns.md (reported line 476)May include surrounding context.

md
- the channel reconnects fine if you manually re-paste the token into the env file

Root cause:
- the service-env writer JSON-encodes string values from `secrets.json` (wrapping them in `"`) and **then** shell-single-quotes the result for the env file
- the resulting line looks like `export CHANNEL_TOKEN='"<token>"'` — the outer single quotes are correct shell quoting, but the inner literal `"` characters become part of the value when the env file is sourced
- the upstream API receives a token with stray leading and trailing `"` chars and rejects it
- the bug only surfaces the next time the env file is regenerated (a host upgrade, certain `doctor --fix` runs, plugin reinstalls), so it presents as "the upgrade broke the channel" rather than a config drift

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

This recovery step tells operators to rewrite env-file secret lines directly from secrets.json, which creates a manual secret-handling path outside the secret-management mechanism. That increases the risk of plaintext credential exposure, persistence in shell history or backups, and inconsistent secret state across future regenerations.

Content

Scanner excerpt · references/failure-patterns.md (reported line 492)May include surrounding context.

md
Recovery:
- back up the env file: `cp <env> <env>.bak-token-fix-<date>`
- rewrite the affected lines using the value from `secrets.json` (which is the canonical clean value), shell-single-quoted with no inner JSON wrapping; only safe if the secret itself contains no single quotes (almost always the case for API tokens)
- restart the gateway through the host service manager
- re-run `openclaw channels status --deep` and confirm the channel reconnects

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill enables implicit invocation without any visible activation constraints, allowing the agent to auto-select this runbook in contexts that only loosely resemble update or debugging tasks. Because the skill is an operational runbook for updating and repairing a system, unintended invocation could trigger risky maintenance guidance in the wrong context, increasing the chance of disruptive or unsafe actions.

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 · references/failure-patterns.md (reported line 176)May include surrounding context.

md
- prefer reconciling install records or reinstalling exact target versions before trusting `openclaw plugins update --all`

Refinement:
- `openclaw plugins registry --refresh` does NOT rewrite the install record's `spec` field. It refreshes `hostContractVersion` and compatibility data only.
- After a refresh, install records can still carry pinned specs like `<plugin>@<older-version>` even when the disk version is `<newer-version>`. `plugins update --all` will then **downgrade** the on-disk plugin to match the pinned spec.
- Correct sequence to actually move a third-party plugin forward:
  1. `openclaw plugins update <id> @<scope>/<pkg>@latest` (note: `update` accepts an explicit spec; this rewrites the install record's spec).

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/failure-patterns.md (reported line 407)May include surrounding context.

md
- reconnecting with a fresh ssh shows the box has actually completed most or all of the work — versions bumped, gateway running, plugins on disk

What's happening:
- when one of the inner steps restarts launchd or replaces the wrapper script the gateway plist sources, the parent shell association can break and the local ssh client stops receiving stdout, even though the remote `zsh -c '...'` keeps running detached and finishes the script.
- the remote orphan can persist as a `zsh -c` process for minutes after the parent ssh exits.

What to inspect:

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/failure-patterns.md (reported line 437)May include surrounding context.

md
- reconnecting with a fresh ssh shows the box has actually completed most or all of the work — versions bumped, gateway running, plugins on disk

What's happening:
- when one of the inner steps restarts launchd or replaces the wrapper script the gateway plist sources, the parent shell association can break and the local ssh client stops receiving stdout, even though the remote `zsh -c '...'` keeps running detached and finishes the script.
- the remote orphan can persist as a `zsh -c` process for minutes after the parent ssh exits.

What to inspect:

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/failure-patterns.md (reported line 860)May include surrounding context.

md
- reconnecting with a fresh ssh shows the box has actually completed most or all of the work — versions bumped, gateway running, plugins on disk

What's happening:
- when one of the inner steps restarts launchd or replaces the wrapper script the gateway plist sources, the parent shell association can break and the local ssh client stops receiving stdout, even though the remote `zsh -c '...'` keeps running detached and finishes the script.
- the remote orphan can persist as a `zsh -c` process for minutes after the parent ssh exits.

What to inspect:

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

Manually rewriting service env files can create persistent plaintext secret state outside the intended secrets layer, and that state survives restarts until regenerated. While not classic session persistence, it does establish durable sensitive configuration in a less controlled location.

Content

Scanner excerpt · references/failure-patterns.md (reported line 492)May include surrounding context.

md
Recovery:
- back up the env file: `cp <env> <env>.bak-token-fix-<date>`
- rewrite the affected lines using the value from `secrets.json` (which is the canonical clean value), shell-single-quoted with no inner JSON wrapping; only safe if the secret itself contains no single quotes (almost always the case for API tokens)
- restart the gateway through the host service manager
- re-run `openclaw channels status --deep` and confirm the channel reconnects

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/failure-patterns.md (reported line 995)May include surrounding context.

md
managed service label
- common package-manager paths such as `/usr/local/node24/bin/openclaw`,
  `/opt/homebrew/bin/openclaw`, and `~/.local/bin/openclaw`
- whether `sudo -H -u <service-user> env PATH=<package-bin>:$PATH openclaw ...`
  reaches the same config and state dir as the gateway

Recovery:

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/failure-patterns.md (reported line 1007)May include surrounding context.

md
Why it matters:
- the login user's missing PATH is not proof OpenClaw is uninstalled
- running `doctor --fix` as the wrong user can inspect or create the wrong
  `~/.openclaw` tree
- service health, config, plugins, and sessions must be audited from the same
  user context as the managed gateway

Static analysis

No suspicious patterns detected.