Back to skill

Security audit

openclaw-upgrade

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent OpenClaw upgrade helper, but it should be reviewed carefully because it performs high-impact package, gateway, scheduled-task, and secret-backup operations with weak safeguards.

Install only if you are comfortable allowing this skill to replace a global OpenClaw package, restart the gateway, inspect local account layout, and create temporary scheduled execution artifacts. Before use, pin and verify the target version and registry, fix the hard-coded Windows path, clean up the scheduled task/script, avoid broad chmod 1777 changes, and protect or remove .env backups after rollback risk has passed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T06 · System Persistence

Warning
Location
SKILL.md:340
Finding
Residual Scheduled Task and Executable Upgrade Script<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 340-369 **Vulnerability Type**: Persistent scheduled execution artifacts **Risk Level**: Medium ### Complete Code Snippet ```powershell # C:\Users\n3186\.openclaw\upgrade-once.ps1 param([string]$Version) $ErrorActionPreference = 'Continue' $log = "$env:USERPROFILE\.openclaw\logs\upgrade-once.log" "$(Get-Date -Format o) 开始升级到 $Version" | Out-File $log -Append # 等 gateway 完全停止(最多 120s) $deadline = (Get-Date).AddSeconds(120) while ((Get-Date) -lt $deadline) { $p = Get-CimInstance Win32_Process -Filter "name='node.exe'" | Where-Object { $_.CommandLine -like '*openclaw*index.js*gateway*' } if (-not $p) { break } Start-Sleep -Seconds 3 } # 安装目标版本(gateway 已停,无 DLL 锁定) npm install -g "openclaw@$Version" *>> $log # 重启 gateway 任务 schtasks /run /tn "OpenClaw Gateway" >> $log 2>&1 "$(Get-Date -Format o) 完成" | Out-File $log -Append ``` ```powershell $st = (Get-Date).AddMinutes(2).ToString('HH:mm') schtasks /create /tn "OpenClaw Upgrade Once" ` /tr "powershell -NoProfile -ExecutionPolicy Bypass -File C:\Users\n3186\.openclaw\upgrade-once.ps1 -Version $target" ` /sc ONCE /st $st /f ``` ### Technical Analysis The Skill instructs the agent to write an executable PowerShell script and register a Windows scheduled task using `ExecutionPolicy Bypass`. The task is scheduled once, so its original purpose is consistent with completing an upgrade after the gateway process stops. However, the procedure does not delete either the task definition or the script after execution. A one-time task does not run periodically by itself, but it remains a cross-session execution artifact that can be manually invoked again. The retained task continues to reference a mutable script. Consequently, a user or process able to modify that script could cause different code to execute when the task is rerun. The `/f` option also overwrites an existing task with the same name without separately confirming ownership. ...[truncated 919 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Delete the scheduled task and upgrade script immediately after completion, including failure paths. - Put cleanup in a `finally` block or a separately guaranteed cleanup action: ```powershell try { # Perform the upgrade. } finally { schtasks /delete /tn "OpenClaw Upgrade Once" /f Remove-Item -LiteralPath $PSCommandPath -Force } ``` - Store the temporary script in a directory whose ACL permits writes only by the intended account and administrators. - Avoid `ExecutionPolicy Bypass` when a signed script or a narrower execution policy can be used. - Generate a unique task name per upgrade and verify that an existing task is owned by the expected workflow before replacing it. - Record and check the script hash before execution. - Configure the task with only the privileges required to replace the OpenClaw package and restart the gateway. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:340
Finding
Hard-Coded Cross-User Script Path and Unsafe Scheduled-Task Command Construction<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 340-369 **Vulnerability Type**: Cross-user path misuse and command argument injection **Risk Level**: High ### Complete Code Snippet ```powershell # C:\Users\n3186\.openclaw\upgrade-once.ps1 param([string]$Version) $ErrorActionPreference = 'Continue' $log = "$env:USERPROFILE\.openclaw\logs\upgrade-once.log" "$(Get-Date -Format o) 开始升级到 $Version" | Out-File $log -Append # 等 gateway 完全停止(最多 120s) $deadline = (Get-Date).AddSeconds(120) while ((Get-Date) -lt $deadline) { $p = Get-CimInstance Win32_Process -Filter "name='node.exe'" | Where-Object { $_.CommandLine -like '*openclaw*index.js*gateway*' } if (-not $p) { break } Start-Sleep -Seconds 3 } npm install -g "openclaw@$Version" *>> $log schtasks /run /tn "OpenClaw Gateway" >> $log 2>&1 "$(Get-Date -Format o) 完成" | Out-File $log -Append ``` ```powershell $st = (Get-Date).AddMinutes(2).ToString('HH:mm') schtasks /create /tn "OpenClaw Upgrade Once" ` /tr "powershell -NoProfile -ExecutionPolicy Bypass -File C:\Users\n3186\.openclaw\upgrade-once.ps1 -Version $target" ` /sc ONCE /st $st /f ``` ### Technical Analysis The scheduled-task command hard-codes `C:\Users\n3186` rather than resolving the profile of the account performing the upgrade. On another host or under another account, this path may belong to a different user, may not exist, or may contain a pre-existing file controlled by someone other than the operator. The `$target` value is embedded directly into the `/tr` command string. Earlier in the workflow it is obtained through `npm view openclaw version`, but the procedure does not require validating it against a strict version grammar before command construction. Quoting the complete task command as a single string leaves command-line parsing dependent on the value's contents. ### Attack Path **Cross-user path scenario:** 1. The workflow runs under an account other than `n3186`. 2. `C:\Users\n3186\.openclaw\upgrade- ...[truncated 1106 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace the hard-coded profile with a canonical current-user path: ```powershell $scriptPath = Join-Path $env:USERPROFILE '.openclaw\upgrade-once.ps1' $scriptPath = [System.IO.Path]::GetFullPath($scriptPath) ``` - Verify that the resolved path is beneath the expected current user's `.openclaw` directory. - Reject symbolic links and reparse points and apply an owner-only ACL before writing the script. - Validate the target with a strict allowlist before using it: ```powershell if ($target -notmatch '^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$') { throw 'Invalid OpenClaw version' } ``` - Use the ScheduledTasks PowerShell API with a separately constructed argument list instead of manually composing an opaque `schtasks /tr` command. - Confirm the script's hash and owner immediately before task registration and execution. - Abort without stopping the gateway if the target path, owner, ACL, or version validation fails. ]]>

T08 · Insecure Dependencies

Error
Location
SKILL.md:238
Finding
Global Installation from a Mutable and Unverified Package Source<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 238-255 and 354-359 **Vulnerability Type**: Third-party package supply-chain exposure **Risk Level**: High ### Complete Code Snippet ```powershell # [Windows] PowerShell $cur = openclaw --version 2>$null $target = npm view openclaw version Write-Host "当前: $cur" Write-Host "最新: $target" npm view "openclaw@$target" engines.node openclaw update status openclaw update --dry-run --tag $target ``` ```powershell # 安装目标版本(gateway 已停,无 DLL 锁定) npm install -g "openclaw@$Version" *>> $log # 重启 gateway 任务 schtasks /run /tn "OpenClaw Gateway" >> $log 2>&1 ``` The routing table and Windows notes also prescribe use of the `npmmirror` registry rather than requiring the official npm registry. ### Technical Analysis The target is selected using mutable registry metadata, and executable package content is then installed globally. The Windows procedure explicitly assumes a third-party npm mirror. The Skill does not require verification of the registry origin, package integrity digest, cryptographic signature, npm provenance, or an administrator-approved version allowlist. An npm installation may execute package lifecycle scripts and installs code that the gateway will subsequently load. A compromised mirror, registry account, DNS path, or package release can therefore change the effective code executed by the workflow after the Skill itself has been reviewed. ### Attack Path 1. An attacker compromises the configured npm registry, mirror, package publisher, or relevant network resolution path. 2. The registry advertises a malicious package version or returns altered package content. 3. The Skill obtains the version through `npm view`. 4. The workflow runs `npm install -g` without independent integrity or provenance verification. 5. Package lifecycle code may execute during installation. 6. The gateway is restarted and loads the installed malicious OpenClaw code. 7. The malicious package receives the ...[truncated 490 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require an approved official registry URL and fail closed when the configured registry differs. - Require the operator to approve an exact target version rather than automatically trusting the latest mutable registry value. - Retrieve and verify a trusted integrity digest, signature, or provenance attestation before installation. - Compare the package digest from the registry against a separately distributed allowlist. - Where feasible, download the package first, inspect it, verify its integrity, and then install the verified local artifact. - Disable npm lifecycle scripts with `--ignore-scripts` unless the package explicitly requires them and those scripts have been reviewed. - Install with the least-privileged account and avoid a shared global prefix where possible. - Ensure TLS certificate validation is enabled and do not silently fall back to untrusted mirrors. - Preserve the previously verified package so rollback does not depend on downloading another mutable artifact. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:263
Finding
Plaintext Duplication and Indefinite Retention of Environment Secrets<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 263-286 **Vulnerability Type**: Insecure backup of credential-bearing files **Risk Level**: Medium ### Complete Code Snippet ```powershell # [Windows] PowerShell $cur = ([regex]::Match((openclaw --version 2>$null), '(\d+\.\d+\.\d+)')).Groups[1].Value Copy-Item "$env:USERPROFILE\.openclaw\openclaw.json" "$env:USERPROFILE\.openclaw\openclaw.json.bak-$cur" -Force Copy-Item "$env:USERPROFILE\.openclaw\.env" "$env:USERPROFILE\.openclaw\.env.bak-$cur" -Force Copy-Item "$env:USERPROFILE\.openclaw\gateway.cmd" "$env:USERPROFILE\.openclaw\gateway.cmd.bak-$cur" -Force # lossless-claw(npm 项目,只备份 package.json,node_modules 不备份) $ll = Get-ChildItem "$env:USERPROFILE\.openclaw\npm\projects" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -like '*lossless-claw*' } | Select-Object -First 1 if ($ll) { Copy-Item "$($ll.FullName)\package.json" "$($ll.FullName)\package.json.bak-$cur" -Force } Get-ChildItem "$env:USERPROFILE\.openclaw" -Filter "*.bak-$cur" | Select-Object Name ``` ```bash # [Linux] bash CURRENT_VER=$(openclaw --version 2>/dev/null | grep -oP '[\d.]+' | head -1) OVERRIDE="$HOME/.config/systemd/user/openclaw-gateway.service.d/override.conf" LOSSLESS_DIR="$HOME/.openclaw/extensions/lossless-claw" cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak-${CURRENT_VER} cp ~/.openclaw/.env ~/.openclaw/.env.bak-${CURRENT_VER} [ -f "$OVERRIDE" ] && cp "$OVERRIDE" "${OVERRIDE}.bak-${CURRENT_VER}" || echo "override.conf 不存在,跳过" ``` ### Technical Analysis The workflow copies `.env`, which commonly contains API keys, tokens, passwords, and service configuration, into predictably named plaintext backup files. It does not verify or enforce restrictive permissions on the destination, encrypt the backup, reject symbolic links or Windows reparse points, or define a retention and secure-deletion policy. On Linux, ordinary `cp` behavior is affected by the process um ...[truncated 1281 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Avoid backing up secrets unless rollback specifically requires them. - Back up only configuration keys that may change during the upgrade rather than copying the entire `.env`. - Encrypt secret-bearing backups using an operating-system-protected key or approved secret-management mechanism. - On Linux, create the backup with owner-only permissions and verify them: ```bash umask 077 install -m 600 -- "$HOME/.openclaw/.env" \ "$HOME/.openclaw/.env.bak-${CURRENT_VER}" ``` - On Windows, apply an ACL granting access only to the intended service account and administrators. - Use no-follow file operations where available and reject symbolic links, junctions, and reparse points. - Refuse to overwrite a pre-existing backup unless its owner, type, and permissions have been verified. - Define a short retention period and securely remove obsolete backups after successful validation. - Document which credentials are present and rotate them if backup permissions or integrity cannot be confirmed. ]]>

other

Note
Location
SKILL.md:151
Finding
Excessive Enumeration of Other User Profiles and Host Instances<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 151-230 **Vulnerability Type**: Excessive host and account reconnaissance **Risk Level**: Low ### Complete Code Snippet ```powershell Write-Host "" Write-Host "=== 其他用户检测 ===" $others = Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -ne $env:USERNAME -and (Test-Path "$($_.FullName)\.openclaw") } if ($others) { Write-Host "⚠️ 发现其他用户含 .openclaw:$($others.Name -join ', ')——npm install -g 影响共享 global 包" } else { Write-Host "未发现其他 OpenClaw 用户 ✅(单用户)" } ``` ```bash # 其他 OpenClaw 用户(同机共享 npm global 风险) echo "" echo "=== 其他 OpenClaw 用户检测 ===" SAME_HOST_USERS="" for U in $(ls /home/ 2>/dev/null); do if [ "$U" != "$(whoami)" ] && [ -d "/home/$U/.openclaw" ]; then echo "用户(同主机): $U"; SAME_HOST_USERS="$SAME_HOST_USERS $U" fi done # WSL 检测(bash 环境可能嵌套 WSL) if command -v powershell.exe &>/dev/null; then WSL_LIST=$(powershell.exe -NoProfile -Command "wsl --list --verbose" 2>/dev/null | grep -i -v "NAME\|Windows" || true) [ -n "$WSL_LIST" ] && echo "$WSL_LIST" && echo "⚠️ 检测到 WSL 实例,注意多实例共享 npm global 风险" fi echo "npm global path: $(npm root -g 2>/dev/null)" if [ -z "$SAME_HOST_USERS" ] && [ -z "$WSL_LIST" ]; then echo "未发现其他 OpenClaw 用户 ✅"; fi ``` ### Technical Analysis The Skill enumerates other Windows user profiles, Linux home directories, OpenClaw directories belonging to other accounts, and WSL instances. The declared purpose is to detect whether a global npm installation could affect multiple users, which is a legitimate concern. However, enumerating every profile and reporting usernames and instance details is broader than the minimum information needed to assess ownership and sharing of the actual npm global prefix. The shown commands do not bypass operating-system permissions and do not themselves read secret files. The primary concern is excessive collection and disclosure of host topology through command output and conver ...[truncated 877 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Ask for explicit permission before inspecting other users or WSL instances. - Determine whether the actual npm global prefix is shared by checking its owner and permissions instead of scanning every home directory. - Report only a boolean result such as “shared installation detected,” without exposing usernames or instance names. - Redact account names and absolute paths from conversation output and persistent logs. - Restrict discovery to the current account unless an administrator explicitly requests host-wide impact analysis. - Do not traverse directories belonging to other users beyond what is necessary to inspect the global package location. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (17)

Credential Access

High
Category
Privilege Escalation
Content
- 2026-08-13(实测事故):`openclaw update`(A 方案)在 Windows 上实测失败——它内部是「先装后停」(Linux 模式),撞 DLL 锁定;且停 gateway 时把自身(gateway 子进程)一起杀死,npm install 根本没执行,gateway 宕机 3.5 小时无人拉起。教训:Windows 主入口改为「分离式 schtasks 一次性任务」,`openclaw update` 在 Windows 上禁用。
- 2026-08-13:合并 Linux 原版 + Windows 适配版为「环境自适应版」。第零步升级为「环境探测 + 分类」(判定 OS 类型 + 服务托管方式),后续每步给出 `[Windows]`/`[Linux]` 双分支。Windows 分支保留 DLL 锁定 + 自杀陷阱两个硬坑(主入口 `openclaw update --tag`),Linux 分支保留原「先装后停」流程。原两个文件已归档到 `SKILL.linux-original.bak.md`(此版之前的 Windows 版内容见 git/历史)。
- 2026-08-13:Windows 适配。本机(SCRIPT-S03-04,Windows Server 2016)实测:gateway 由 Windows 任务计划程序(schtasks)托管而非 systemd;gateway 进程加载了 node-pty-win32-x64 / tree-sitter 等原生 .node DLL,Windows 锁定运行中 DLL → 运行时直接 `npm install -g openclaw` 会 EBUSY/EPERM 失败;agent 运行在 gateway 进程内部不能自己 stop 自己。故 Windows 主入口改为 `openclaw update --tag <版本>`,裸 npm install 降级为分离式 schtasks 任务兜底。同时适配:npm registry=npmmirror(无代理)、无 curl.exe(Server 2016)改用 Invoke-WebRequest、.env 无 GITHUB_TOKEN、lossless-claw 是 npm 项目路径、消息通道 POPO 无 feishu。
- 上次(4.14版本)因为没检查 lossless-claw 兼容性踩过坑
- 上次升级后忘记发完成通知,爸比等了7小时不知道结果
- 2026-07-27:NAS欢欢用自写脚本升级,脚本从gateway进程内部nohup启动,第一步systemctl stop把整个进程组一起杀掉,脚本自己被杀死,npm install根本没跑起来,gateway停了近6小时无人察觉——本skill的流程设计(npm install前不停服务、重启只在最后单独一步、重启前先设好通知cron)天然规避了这个坑,但重启这一步本身如果裸调systemctl也仍有被自身进程树波及的理论风险,已在第八步/回滚方案中改为优先走平台 gateway 工具
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- 2026-08-13(实测事故):`openclaw update`(A 方案)在 Windows 上实测失败——它内部是「先装后停」(Linux 模式),撞 DLL 锁定;且停 gateway 时把自身(gateway 子进程)一起杀死,npm install 根本没执行,gateway 宕机 3.5 小时无人拉起。教训:Windows 主入口改为「分离式 schtasks 一次性任务」,`openclaw update` 在 Windows 上禁用。
- 2026-08-13:合并 Linux 原版 + Windows 适配版为「环境自适应版」。第零步升级为「环境探测 + 分类」(判定 OS 类型 + 服务托管方式),后续每步给出 `[Windows]`/`[Linux]` 双分支。Windows 分支保留 DLL 锁定 + 自杀陷阱两个硬坑(主入口 `openclaw update --tag`),Linux 分支保留原「先装后停」流程。原两个文件已归档到 `SKILL.linux-original.bak.md`(此版之前的 Windows 版内容见 git/历史)。
- 2026-08-13:Windows 适配。本机(SCRIPT-S03-04,Windows Server 2016)实测:gateway 由 Windows 任务计划程序(schtasks)托管而非 systemd;gateway 进程加载了 node-pty-win32-x64 / tree-sitter 等原生 .node DLL,Windows 锁定运行中 DLL → 运行时直接 `npm install -g openclaw` 会 EBUSY/EPERM 失败;agent 运行在 gateway 进程内部不能自己 stop 自己。故 Windows 主入口改为 `openclaw update --tag <版本>`,裸 npm install 降级为分离式 schtasks 任务兜底。同时适配:npm registry=npmmirror(无代理)、无 curl.exe(Server 2016)改用 Invoke-WebRequest、.env 无 GITHUB_TOKEN、lossless-claw 是 npm 项目路径、消息通道 POPO 无 feishu。
- 上次(4.14版本)因为没检查 lossless-claw 兼容性踩过坑
- 上次升级后忘记发完成通知,爸比等了7小时不知道结果
- 2026-07-27:NAS欢欢用自写脚本升级,脚本从gateway进程内部nohup启动,第一步systemctl stop把整个进程组一起杀掉,脚本自己被杀死,npm install根本没跑起来,gateway停了近6小时无人察觉——本skill的流程设计(npm install前不停服务、重启只在最后单独一步、重启前先设好通知cron)天然规避了这个坑,但重启这一步本身如果裸调systemctl也仍有被自身进程树波及的理论风险,已在第八步/回滚方案中改为优先走平台 gateway 工具
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
# /tmp/jiti 权限(codex EACCES 坑)
if [ -d "/tmp/jiti" ]; then
  JITI_PERM=$(stat -c "%a" /tmp/jiti)
  [ "$JITI_PERM" != "1777" ] && echo "⚠️ /tmp/jiti 权限 $JITI_PERM,建议 sudo chmod 1777 /tmp/jiti" || echo "/tmp/jiti: 1777 ✅"
else
  echo "/tmp/jiti: 不存在 ✅"
fi
Confidence
80% confidence
Finding
Changing a temporary directory to mode 1777 is a powerful filesystem operation that can alter trust boundaries for any process using that path. In an automation skill, recommending such a broad permission change without validation can facilitate tampering or unsafe shared-directory usage.

Credential Access

High
Category
Privilege Escalation
Content
# [Windows] PowerShell
$cur = ([regex]::Match((openclaw --version 2>$null), '(\d+\.\d+\.\d+)')).Groups[1].Value
Copy-Item "$env:USERPROFILE\.openclaw\openclaw.json" "$env:USERPROFILE\.openclaw\openclaw.json.bak-$cur" -Force
Copy-Item "$env:USERPROFILE\.openclaw\.env"            "$env:USERPROFILE\.openclaw\.env.bak-$cur" -Force
Copy-Item "$env:USERPROFILE\.openclaw\gateway.cmd"     "$env:USERPROFILE\.openclaw\gateway.cmd.bak-$cur" -Force
# lossless-claw(npm 项目,只备份 package.json,node_modules 不备份)
$ll = Get-ChildItem "$env:USERPROFILE\.openclaw\npm\projects" -Directory -ErrorAction SilentlyContinue |
Confidence
94% confidence
Finding
The workflow explicitly copies .env, which commonly contains secrets, into version-suffixed backup files. This proliferates credential-bearing material on disk, increases the number of secret copies that must be protected, and may leave readable backups in locations with broader retention, sync, or access than intended.

Credential Access

High
Category
Privilege Escalation
Content
LOSSLESS_DIR="$HOME/.openclaw/extensions/lossless-claw"

cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak-${CURRENT_VER}
cp ~/.openclaw/.env ~/.openclaw/.env.bak-${CURRENT_VER}
[ -f "$OVERRIDE" ] && cp "$OVERRIDE" "${OVERRIDE}.bak-${CURRENT_VER}" || echo "override.conf 不存在,跳过"
# lossless-claw:node_modules>500MB 时只备份 package.json/plugin.json/dist
if [ -d "$LOSSLESS_DIR" ]; then
Confidence
94% confidence
Finding
The Linux backup step duplicates ~/.openclaw/.env into a separate backup file, creating additional local copies of credentials or tokens. Secret duplication materially increases exposure through misconfigured permissions, backups, shell access by other users, or later accidental disclosure.

Credential Access

High
Category
Privilege Escalation
Content
$prev = '<回退版本,如 2026.6.6>'
npm install -g "openclaw@$prev"   # gateway 需先停,参照第六步 A 兜底分离式任务
Copy-Item "$env:USERPROFILE\.openclaw\openclaw.json.bak-$prev" "$env:USERPROFILE\.openclaw\openclaw.json" -Force
Copy-Item "$env:USERPROFILE\.openclaw\.env.bak-$prev"            "$env:USERPROFILE\.openclaw\.env" -Force
Copy-Item "$env:USERPROFILE\.openclaw\gateway.cmd.bak-$prev"     "$env:USERPROFILE\.openclaw\gateway.cmd" -Force
# 优先 gateway 工具 action=restart,无工具才:schtasks /run /tn "OpenClaw Gateway"
```
Confidence
92% confidence
Finding
The Windows rollback path restores a .env backup, confirming that secret-bearing backup artifacts are part of the normal process. This entrenches a pattern of duplicating and reusing credentials from flat files, which broadens the attack surface and makes secret hygiene harder to enforce.

Credential Access

High
Category
Privilege Escalation
Content
PREV_VER=<回退版本>
npm install -g openclaw@${PREV_VER}
cp ~/.openclaw/openclaw.json.bak-${PREV_VER} ~/.openclaw/openclaw.json
cp ~/.openclaw/.env.bak-${PREV_VER} ~/.openclaw/.env
OVERRIDE="$HOME/.config/systemd/user/openclaw-gateway.service.d/override.conf"
[ -f "${OVERRIDE}.bak-${PREV_VER}" ] && cp "${OVERRIDE}.bak-${PREV_VER}" "$OVERRIDE"
LOSSLESS_BAK=$(ls -d "$HOME/.openclaw/extensions/lossless-claw.bak-"* 2>/dev/null | sort | tail -1)
Confidence
92% confidence
Finding
The Linux rollback step restores ~/.openclaw/.env from a backup file, again relying on duplicated credential material stored locally. In multi-user or backup-integrated systems, this raises the probability of unauthorized access to long-lived secrets.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
OVERRIDE="$HOME/.config/systemd/user/openclaw-gateway.service.d/override.conf"
[ -f "${OVERRIDE}.bak-${PREV_VER}" ] && cp "${OVERRIDE}.bak-${PREV_VER}" "$OVERRIDE"
LOSSLESS_BAK=$(ls -d "$HOME/.openclaw/extensions/lossless-claw.bak-"* 2>/dev/null | sort | tail -1)
[ -n "$LOSSLESS_BAK" ] && rm -rf "$HOME/.openclaw/extensions/lossless-claw" && cp -r "$LOSSLESS_BAK" "$HOME/.openclaw/extensions/lossless-claw"
systemctl --user daemon-reload
# 优先 gateway 工具 action=restart,无工具才:systemctl --user restart openclaw-gateway.service
```
Confidence
88% confidence
Finding
The rollback procedure includes rm -rf on a user-controlled path derived from filesystem state. Although the path is partially constrained, recursive deletion in automation is dangerous because mistakes, path manipulation, or unexpected variable values can lead to destructive data loss beyond the intended plugin directory.

Chaining Abuse

High
Category
Tool Misuse
Content
OVERRIDE="$HOME/.config/systemd/user/openclaw-gateway.service.d/override.conf"
[ -f "${OVERRIDE}.bak-${PREV_VER}" ] && cp "${OVERRIDE}.bak-${PREV_VER}" "$OVERRIDE"
LOSSLESS_BAK=$(ls -d "$HOME/.openclaw/extensions/lossless-claw.bak-"* 2>/dev/null | sort | tail -1)
[ -n "$LOSSLESS_BAK" ] && rm -rf "$HOME/.openclaw/extensions/lossless-claw" && cp -r "$LOSSLESS_BAK" "$HOME/.openclaw/extensions/lossless-claw"
systemctl --user daemon-reload
# 优先 gateway 工具 action=restart,无工具才:systemctl --user restart openclaw-gateway.service
```
Confidence
86% confidence
Finding
The command chains a non-empty backup check with rm -rf and copy operations using &&, combining destructive deletion and restoration into a single line with little opportunity for validation or recovery. If the backup path or target path is wrong, the operator can lose the live plugin directory immediately and replace it with unintended content.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The description says the skill must run whenever the user says phrases like "升级openclaw", "openclaw升级", or "更新openclaw". These are generic natural-language phrases rather than narrowly scoped commands, and the file does not provide exclusion conditions or negative examples to clarify when discussion of an upgrade should not invoke the skill.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The manifest description and the entire skill content prescribe operation in Chinese, including required reporting to the user in that language, but there is no opt-in or alternative language path. This is a natural-language policy concern because it imposes a locale/language behavior for all uses without explicit user choice or a documented region-specific requirement.

Session Persistence

Medium
Category
Rogue Agent
Content
- 2026-08-13:Windows 适配。本机(SCRIPT-S03-04,Windows Server 2016)实测:gateway 由 Windows 任务计划程序(schtasks)托管而非 systemd;gateway 进程加载了 node-pty-win32-x64 / tree-sitter 等原生 .node DLL,Windows 锁定运行中 DLL → 运行时直接 `npm install -g openclaw` 会 EBUSY/EPERM 失败;agent 运行在 gateway 进程内部不能自己 stop 自己。故 Windows 主入口改为 `openclaw update --tag <版本>`,裸 npm install 降级为分离式 schtasks 任务兜底。同时适配:npm registry=npmmirror(无代理)、无 curl.exe(Server 2016)改用 Invoke-WebRequest、.env 无 GITHUB_TOKEN、lossless-claw 是 npm 项目路径、消息通道 POPO 无 feishu。
- 上次(4.14版本)因为没检查 lossless-claw 兼容性踩过坑
- 上次升级后忘记发完成通知,爸比等了7小时不知道结果
- 2026-07-27:NAS欢欢用自写脚本升级,脚本从gateway进程内部nohup启动,第一步systemctl stop把整个进程组一起杀掉,脚本自己被杀死,npm install根本没跑起来,gateway停了近6小时无人察觉——本skill的流程设计(npm install前不停服务、重启只在最后单独一步、重启前先设好通知cron)天然规避了这个坑,但重启这一步本身如果裸调systemctl也仍有被自身进程树波及的理论风险,已在第八步/回滚方案中改为优先走平台 gateway 工具
- 2026-07-27(同一事故的第二个坑):NAS欢欢手动拉起gateway后agent恢复中断会话继续把npm包升到2026.7.1-2,但机器Node还是22.22.1,openclaw 2026.7.1-2要求Node≥22.22.3,gateway直接拒绝启动;且该NAS访问registry.npmjs.org走IPv6比IPv4慢6倍,codex插件依赖安装卡在慢速IPv6上4分半——第零步此前没查Node版本、没做IPv4/IPv6测速,两个真实缺口已补入
- 2026-07-27(第三个坑,元问题):description字段被写成changelog摘要,覆盖了触发关键词,导致agent在用户说"升级openclaw"时语义匹配不上这个skill。教训:description只写"什么场景触发",绝不写"这次改了什么";changelog一律写在本节。
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
- 2026-08-13:Windows 适配。本机(SCRIPT-S03-04,Windows Server 2016)实测:gateway 由 Windows 任务计划程序(schtasks)托管而非 systemd;gateway 进程加载了 node-pty-win32-x64 / tree-sitter 等原生 .node DLL,Windows 锁定运行中 DLL → 运行时直接 `npm install -g openclaw` 会 EBUSY/EPERM 失败;agent 运行在 gateway 进程内部不能自己 stop 自己。故 Windows 主入口改为 `openclaw update --tag <版本>`,裸 npm install 降级为分离式 schtasks 任务兜底。同时适配:npm registry=npmmirror(无代理)、无 curl.exe(Server 2016)改用 Invoke-WebRequest、.env 无 GITHUB_TOKEN、lossless-claw 是 npm 项目路径、消息通道 POPO 无 feishu。
- 上次(4.14版本)因为没检查 lossless-claw 兼容性踩过坑
- 上次升级后忘记发完成通知,爸比等了7小时不知道结果
- 2026-07-27:NAS欢欢用自写脚本升级,脚本从gateway进程内部nohup启动,第一步systemctl stop把整个进程组一起杀掉,脚本自己被杀死,npm install根本没跑起来,gateway停了近6小时无人察觉——本skill的流程设计(npm install前不停服务、重启只在最后单独一步、重启前先设好通知cron)天然规避了这个坑,但重启这一步本身如果裸调systemctl也仍有被自身进程树波及的理论风险,已在第八步/回滚方案中改为优先走平台 gateway 工具
- 2026-07-27(同一事故的第二个坑):NAS欢欢手动拉起gateway后agent恢复中断会话继续把npm包升到2026.7.1-2,但机器Node还是22.22.1,openclaw 2026.7.1-2要求Node≥22.22.3,gateway直接拒绝启动;且该NAS访问registry.npmjs.org走IPv6比IPv4慢6倍,codex插件依赖安装卡在慢速IPv6上4分半——第零步此前没查Node版本、没做IPv4/IPv6测速,两个真实缺口已补入
- 2026-07-27(第三个坑,元问题):description字段被写成changelog摘要,覆盖了触发关键词,导致agent在用户说"升级openclaw"时语义匹配不上这个skill。教训:description只写"什么场景触发",绝不写"这次改了什么";changelog一律写在本节。
Confidence
80% 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.

External Transmission

Medium
Category
Data Exfiltration
Content
echo "⚠️ 仅确认当前 Node 不够,必须第一步拿到目标版本 engines.node 后对比。"

# 代理检测
if curl -s --connect-timeout 3 -x "http://127.0.0.1:7890" https://registry.npmjs.org/ > /dev/null 2>&1; then
  PROXY_OPT="--proxy http://127.0.0.1:7890"; echo "代理: 127.0.0.1:7890 ✅"
elif curl -s --connect-timeout 3 https://registry.npmjs.org/ > /dev/null 2>&1; then
  PROXY_OPT=""; echo "代理: 直连 ✅"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# /tmp/jiti 权限(codex EACCES 坑)
if [ -d "/tmp/jiti" ]; then
  JITI_PERM=$(stat -c "%a" /tmp/jiti)
  [ "$JITI_PERM" != "1777" ] && echo "⚠️ /tmp/jiti 权限 $JITI_PERM,建议 sudo chmod 1777 /tmp/jiti" || echo "/tmp/jiti: 1777 ✅"
else
  echo "/tmp/jiti: 不存在 ✅"
fi
Confidence
72% confidence
Finding
Recommending chmod 1777 on /tmp/jiti creates a world-writable sticky directory, which can introduce tampering or symlink/hijack risks if the path is later trusted by privileged or security-sensitive processes. In a maintenance skill, such blanket permission changes normalize unsafe filesystem practices and may weaken host integrity.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# /tmp/jiti 权限(codex EACCES 坑)
if [ -d "/tmp/jiti" ]; then
  JITI_PERM=$(stat -c "%a" /tmp/jiti)
  [ "$JITI_PERM" != "1777" ] && echo "⚠️ /tmp/jiti 权限 $JITI_PERM,建议 sudo chmod 1777 /tmp/jiti" || echo "/tmp/jiti: 1777 ✅"
else
  echo "/tmp/jiti: 不存在 ✅"
fi
Confidence
80% confidence
Finding
Recommending chmod 1777 on /tmp/jiti creates a world-writable sticky directory, which can introduce tampering or symlink/hijack risks if the path is later trusted by privileged or security-sensitive processes. In a maintenance skill, such blanket permission changes normalize unsafe filesystem practices and may weaken host integrity.

External Transmission

Medium
Category
Data Exfiltration
Content
npm view openclaw@${TARGET_VER} engines.node
# 发行说明(有 GITHUB_TOKEN 时):
curl -s -H "Authorization: token $GITHUB_TOKEN" \
  "https://api.github.com/repos/openclaw/openclaw/releases/tags/v${TARGET_VER}" | \
  python3 -c "import json,sys; print(json.load(sys.stdin).get('body','')[:3000])"
```
Confidence
77% confidence
Finding
The skill instructs sending an Authorization header with $GITHUB_TOKEN to api.github.com. Even though this is a legitimate API call, embedding token-bearing outbound requests in a broadly triggered skill increases the chance of unnecessary credential use, accidental disclosure in logs, or use in environments where such access should be avoided.

Static analysis

Detected: suspicious.destructive_delete_command

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
SKILL.md:468