Back to skill

Security audit

OCTOOL for backup

Security checks for vulnerabilities and agentic risk

Overview

This backup assistant is not proven malicious, but it should go to Review because it generates powerful shell commands and has verified flaws that could expose a GitHub token or make copied commands unsafe.

Review carefully before installing. Use only trusted openclaw.json files and trusted repositories, avoid the broad classic repo token link, prefer a fine-grained token limited to one private backup repository, and inspect any copied shell commands before running them, especially commands that modify ~/.bash_profile, install packages, or restore files.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
oc-tool.html:1694
Finding

Shell command injection through imported Openclaw configuration

Content
View full analysis
({ id: a.id, name: a.name || a.id, model: a.model || '', workspace: a.workspace || `~/.openclaw/workspace-${a.id}` })); ``` The imported values are later inserted directly into shell commands: ```javascript const agentBackupLines = agents.map(a => { const wsName = `workspace-${a.id}`; return [ ` mkdir -p ${wsName}`, ` for f in MEMORY.md SOUL.md IDENTITY.md AGENTS.md USER.md HEARTBEAT.md TOOLS.md; do`, ` [ -f ${a.workspace}/$f ] && cp ${a.workspace}/$f ${wsName}/$f`, ` done` ].join('\n'); }).join('\n\n'); const agentRestoreLines = agents.map(a => { return ` [ -d workspace-${a.id} ] && rsync -a workspace-${a.id}/ ${a.workspace}/`; }).join('\n'); const migrateWsLines = agents.map(a => { return `rsync -a ~/dotfiles/workspace-${a.id}/ ${a.workspace}/`; }).join('\n'); ``` ### Technical Analysis The `id` and `workspace` fields are read from a user-selected JSON file and retained without validation. They are subsequently interpolated into shell scripts without quoting or escaping. Although the application defines `sanitizePath`, it is not applied to these imported fields. Shell control operators, command substitutions, redirections, whitespace, and other metacharacters can therefore change the meaning of the generated script. This also contradicts the project documentation's assertion that all values flowing into generated shell commands are validated. ### Attack Path 1. An attacker prepares an `openclaw.json` file containing a malicious `id` or `workspace` value with embedded shell syntax. 2. The attacker persuades the victim to import that file into the assistant. 3. The assistant parses the file and generate ...[truncated 802 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
oc-tool.html:2338
Finding

Shell command injection through an unvalidated repository URL

Content
View full analysis
'; const wsLines = ST.agents.map(a => `rsync -a ~/dotfiles/workspace-${a.id}/ ${a.workspace}/`).join('\\n'); const gitCmd = `git clone ${repoUrl} ~/dotfiles cp ~/dotfiles/bash_profile ~/.bash_profile && source ~/.bash_profile cp ~/dotfiles/openclaw.json ~/.openclaw/openclaw.json ${wsLines} rsync -a ~/dotfiles/skills/ ~/.openclaw/skills/ npm install -g openclaw brew install ollama && ollama pull nomic-embed-text `; setBoxText('migrate-git-cmd', gitCmd); } ``` The repository value is initially accepted without strict URL parsing: ```javascript const repo = document.getElementById('go-repo-url').value.trim(); if (!repo) { statusEl.textContent = '[Err] 请填写仓库 URL'; return; } ST.repoUrl = repo; ``` ### Technical Analysis The repository value is treated as an arbitrary string. It is transformed with simple string replacement for API access and later inserted unquoted into a `git clone` shell command. The code does not parse the value with the browser `URL` API, enforce an HTTPS GitHub origin, validate owner and repository components, or reject shell metacharacters. A repository string containing shell syntax can consequently append commands to the generated migration script. ### Attack Path 1. An attacker supplies or recommends a specially crafted repository value containing shell operators or a newline. 2. The victim enters that value into the Git connection interface. 3. The application stores it in `ST.repoUrl`. 4. `renderMigrateCmds` inserts the value into the generated `git clone` command. 5. The victim copies and runs the migration block. 6. The shell interprets the attacker-controlled portion as an ...[truncated 361 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
oc-tool.html:2309
Finding

DOM cross-site scripting through imported and GitHub-controlled metadata

Content
View full analysis
${msg}`; } ``` Messages passed to it can contain imported agent names and model values: ```javascript wzStatus('wz-0-status', 'ok', `${ST.agents.map(a => a.name + ' (' + a.model.split('/').pop() + ')').join(' · ')}`); ``` GitHub tag names and commit messages are also rendered as HTML: ```javascript function renderVersionList() { const wrap = document.getElementById('rs-ver-wrap'); if (!ST.allTags.length) { wrap.innerHTML = '
暂无备份请先执行 oc-save 创建第一个备份
'; return; } wrap.innerHTML = '
' + ST.allTags.map((t, i) => `
${t.name}${t.commit?.message || ''}
` ).join('') + '
'; } ``` Imported agent values are placed in markup and an inline JavaScript handler: ```javascript function renderAgentBtns() { const wrap = document.getElementById('ab-agent-btns'); wrap.innerHTML = [ `~/.openclaw/`, ...ST.agents.map(a => `${a.name}`) ].join(''); } ``` ### Technical Analysis Agent IDs, names, and model strings originate in an imported file. Tag names and commit messages originate from GitHub API responses. These values are inserted i ...[truncated 1575 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
oc-tool.html:1307
Finding

GitHub token acquisition requests privileges broader than necessary

Content
View full analysis
GitHub Token (需 repo 读写权限): 获取 Token ↗ ``` ### Technical Analysis The direct token-creation link requests the classic GitHub `repo` scope. That scope can grant broad control over private repositories available to the token owner, while the declared functionality only requires reading repository metadata and reading or writing contents in one selected backup repository. The documentation recommends a fine-grained token restricted to the target repository, but the actionable link directs users toward a broader classic token. This exceeds the minimum privileges needed by the assistant. The excessive scope becomes especially significant in combination with the DOM-XSS vulnerability, because the PAT is retained in `sessionStorage` while the page is open. ### Attack Path 1. The victim follows the token-generation link offered by the interface. 2. GitHub creates a classic PAT with the broad `repo` scope after user authorization. 3. The victim enters the token into the application, which stores it in `sessionStorage`. 4. The token is exposed through browser compromise, malicious extensions, local access, or the identified DOM-XSS path. 5. An attacker uses the token against repositories beyond the single backup repository intended for this Skill. ### Impact Assessment Depending on the victim's GitHub account and token authorization, compromise may expose private source code and permit repository content modification across multiple repositories. The exact scope remains bounded by the permissions GitHub grants to the PAT and the account owning it, but it is materially broader tha ...[truncated 65 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
oc-tool.html:2339
Finding

Migration commands install unpinned global dependencies

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (17)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · oc-tool.html (reported line 2)May include surrounding context.

html
<!DOCTYPE html>
<!--
  oc-tool.html — Openclaw Backup Assistant (OC Tool)
  Author: donnieclaw | License: MIT-0
  Version: 1.1.0

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 · oc-tool.html (reported line 23)May include surrounding context.

html
using the tool without entering a GitHub token — zero requests.

  CREDENTIAL HANDLING:
  - GitHub Personal Access Token (PAT): collected only when the user
    enables Git mode. Stored in sessionStorage (NOT localStorage),
    so it is automatically cleared when the browser tab is closed.
    It is transmitted only to api.github.com via the Authorization

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The tool claims all user-supplied values are validated before shell interpolation, but generateSetupCmd() interpolates agent IDs and workspace paths from uploaded openclaw.json directly into shell commands without sanitization or shell escaping. A crafted JSON file could inject shell metacharacters into the generated script, leading to arbitrary command execution when the user pastes it into a terminal.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The comment block explicitly claims there is no clipboard access, but the implementation later performs clipboard writes. In a tool that generates shell commands and handles a GitHub token, false security claims materially increase risk because users may trust and execute copied content under incorrect assumptions.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · oc-tool.html (reported line 1168)May include surrounding context.

html
<body>

  <!-- ══ WIZARD ══ -->
  <div id="wizard">
    <div class="wz-box" style="max-width:680px;">
      <div class="wz-logo">OC Tool</div>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · oc-tool.html (reported line 1345)May include surrounding context.

html
</div>
      </div>

      <!-- main -->
      <div class="main">
        <div class="topbar">
          <div class="topbar-title" id="topbar-title">备份</div>

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · oc-tool.html (reported line 1478)May include surrounding context.

html
<button class="btn full"
                      onclick="chipCopy(document.querySelector('#migrate-git-cmd .copy-chip'))">[List] 复制迁移命令</button>
                    <div class="box w" style="margin-top:10px"><strong>注意</strong>Gemini OAuth token 无法备份,新机器需重新登录。API
                      key 在 .env 里无需重配。</div>
                  </div>
                </div>
              </div>

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · oc-tool.html (reported line 2401)May include surrounding context.

html
const el = document.getElementById('ab-plines');
      if (!ST.profileLines.length) { el.innerHTML = '<div class="box i" style="margin:0"><strong>提示</strong>连接 GitHub 后显示</div>'; return; }
      const ag = ST.ab.agent;
      const filters = { root: l => l.text.includes('bash_profile') || l.text.includes('openclaw.json') || l.text.includes('.env') || l.text.includes('skills/') };
      ST.agents.forEach(a => { filters[a.id] = l => l.text.includes('workspace-' + a.id); });
      const match = filters[ag] || (() => true);
      el.innerHTML = ST.profileLines.map((l, i) => {

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

Storing a GitHub PAT in browser sessionStorage still exposes the credential to any script executing in the same origin, including future XSS or compromised local content loaded from that page context. Although sessionStorage is better than localStorage and is scoped to the tab lifetime, it remains a client-side persistence mechanism for sensitive credentials.

Content

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

md
### 🔒 Privacy & Security (Please Read)
- **True Zero External Tracking**: All external dependencies have been removed. This tool runs 100% client-side in your local browser sandbox. The only external call is to `api.github.com` when you explicitly opt into Git mode. You can verify offline safety by opening DevTools > Network — zero requests without a GitHub token.
- **Credential Handling**: The GitHub PAT is used only for two `api.github.com` calls: `GET /repos/{owner}/{repo}` (verify access) and `PUT /repos/{owner}/{repo}/contents/{path}` (write backup). The token is stored in `sessionStorage` only — **it is automatically cleared when the tab is closed** and is never written to `localStorage`. We recommend a fine-grained PAT scoped to `Contents: Read and Write` on the target repo only.
- **Proxy Detection**: The generated `oc()` command detects system proxy using native macOS `scutil --proxy` piped through `awk`. No `node -e`, no `eval`, no dynamic code execution. Read-only syscall only.
- **Shell Command Generation**: This tool generates `sed`, `rsync`, `cp`, and `git` commands displayed as plaintext for your review. **No commands are auto-executed.** The `bash_profile` write command includes an idempotent guard (`OC_TOOL_BLOCK` marker check) — safe to run multiple times. All user inputs that flow into generated shell commands (paths, tags, commit messages, rsync excludes) are validated at generation time; inputs containing shell metacharacters are rejected with a visible error.
- **Local File Reading**: Files are read only when you explicitly drag them into the drop zone via the browser File API. No background disk access occurs.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- **True Zero External Tracking**: All external dependencies have been removed. This tool runs 100% client-side in your local browser sandbox. The only external call is to `api.github.com` when you explicitly opt into Git mode. You can verify offline safety by opening DevTools > Network — zero requests without a GitHub token.
- **Credential Handling**: The GitHub PAT is used only for two `api.github.com` calls: `GET /repos/{owner}/{repo}` (verify access) and `PUT /repos/{owner}/{repo}/contents/{path}` (write backup). The token is stored in `sessionStorage` only — **it is automatically cleared when the tab is closed** and is never written to `localStorage`. We recommend a fine-grained PAT scoped to `Contents: Read and Write` on the target repo only.
- **Proxy Detection**: The generated `oc()` command detects system proxy using native macOS `scutil --proxy` piped through `awk`. No `node -e`, no `eval`, no dynamic code execution. Read-only syscall only.
- **Shell Command Generation**: This tool generates `sed`, `rsync`, `cp`, and `git` commands displayed as plaintext for your review. **No commands are auto-executed.** The `bash_profile` write command includes an idempotent guard (`OC_TOOL_BLOCK` marker check) — safe to run multiple times. All user inputs that flow into generated shell commands (paths, tags, commit messages, rsync excludes) are validated at generation time; inputs containing shell metacharacters are rejected with a visible error.
- **Local File Reading**: Files are read only when you explicitly drag them into the drop zone via the browser File API. No background disk access occurs.

## How to start / 启动方式

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document sets lang="zh", and the visible UI, prompts, warnings, and action labels throughout the tool are predominantly in Chinese. This creates a language/locale policy issue because the skill does not offer users an explicit language choice or opt-in before enforcing a specific locale.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest frames this skill as a visual configuration assistant for backup and workspace migration, but the generated oc() shell function force-kills any process listening on port 18789 and starts the Openclaw gateway. Service management is broader than backup/migration and is not an obvious implementation detail of repository backup or workspace transfer.

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 · oc-tool.html (reported line 1891)May include surrounding context.

html
fi
}`;

            // ── IDEMPOTENT WRITE ──────────────────────────────────────────────────────
      // SECURITY: Checks for OC_TOOL_BLOCK marker before appending to bash_profile.
      // Running the generated command multiple times is safe — functions are only
      // inserted once. No unconditional >> append.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The migration commands do more than restore backed-up files: they install openclaw, install ollama via Homebrew, and pull a model. This goes beyond local/Git backup and workspace migration into software provisioning and network-backed dependency setup, which the manifest does not mention.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · oc-tool.html (reported line 2463)May include surrounding context.

html
async function ghFetch(path) {
      const headers = { Accept: 'application/vnd.github.v3+json' };
      if (ST.ghToken) headers.Authorization = `token ${ST.ghToken}`;
      const r = await fetch(`https://api.github.com/${path}`, { headers });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      return r.json();
    }

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · oc-tool.html (reported line 2470)May include surrounding context.

html
async function ghFetch(path) {
      const headers = { Accept: 'application/vnd.github.v3+json' };
      if (ST.ghToken) headers.Authorization = `token ${ST.ghToken}`;
      const r = await fetch(`https://api.github.com/${path}`, { headers });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      return r.json();
    }

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code uses navigator.clipboard.writeText and a fallback document.execCommand('copy'), despite the security declaration claiming no clipboard access. This mismatch is dangerous because it misleads users and reviewers about what browser capabilities the tool invokes, reducing informed consent around copied shell commands and tokens.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.