Back to skill

Security audit

Claw Backup

Security checks across malware telemetry and agentic risk

Overview

This is a transparent backup skill that handles sensitive OpenClaw data and scheduling, but those behaviors match its stated purpose and are disclosed.

Install only after reviewing setup.js, install-launchagent.sh, and the generated backup_enhanced.sh. Prefer the git clone path, avoid the curl-to-node shortcut, test local-only first, confirm exactly which directories are archived, verify the rclone destination and retention settings, and use encrypted storage for cloud backups.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (21)

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The generated backup script collects materially more data than a user would infer from the manifest/restore notes, including ~/.openclaw config, workspace data, modules, scripts, and much of a local development tree. In a backup tool, over-collection is a real security/privacy issue because it increases the chance that secrets, proprietary code, personal notes, or unrelated files are archived and later uploaded to cloud storage.

Context-Inappropriate Capability

Low
Confidence
77% confidence
Finding
The manifest records hostname and full uname output, which creates host fingerprinting metadata beyond what is strictly necessary to restore files. While low severity, this expands the sensitivity of the backup artifact and can disclose device identity and environment details if the archive is exposed.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
In --defaults mode, the setup silently generates a script configured to upload backups to a remote rclone destination, without an explicit warning at generation time about off-device data transmission or the contents being sent. Because the backup scope includes potentially sensitive user data and code, this can lead to unintended cloud exfiltration once the script is run.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The setup writes an executable shell script and scheduling-related files to disk, and may replace existing files after renaming them to .bak, without a strong upfront warning that filesystem changes are being made. This is a real but low-severity safety issue because users may unintentionally create runnable persistence artifacts or overwrite expected automation files.

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.

## Troubleshooting
Confidence
83% confidence
Finding
crontab -e

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.
Confidence
85% confidence
Finding
launchctl load` — no sudo for the agent). Or run the universal install

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.
Confidence
85% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.
Confidence
85% confidence
Finding
launchctl load

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.
Confidence
85% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
## Schedule (optional)

- **macOS:** The setup generates a LaunchAgent plist. Install with the printed commands (copy to `~/Library/LaunchAgents/` and `launchctl load` — no sudo for the agent). Or run the universal installer: `./install-launchagent.sh` (it searches common locations; if your project is elsewhere, pass the plist path: `./install-launchagent.sh /path/to/com.openclaw.backup.plist`). If you had an old system-wide daemon, the installer may ask for your password once to remove it. Backup runs at the hour/minute configured during setup.
- **Linux:** Add the printed cron line to `crontab -e`.
- **Windows:** Use Task Scheduler to run the backup script daily via Git Bash or WSL.
Confidence
85% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
# ---- Install LaunchAgent ----
mkdir -p "$LAUNCH_AGENTS"
cp "$FOUND_PLIST" "$AGENT_PLIST"
echo "Installed: $AGENT_PLIST"

# Load (idempotent: unload first if already loaded to pick up plist changes)
Confidence
74% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
# ---- Install LaunchAgent ----
mkdir -p "$LAUNCH_AGENTS"
cp "$FOUND_PLIST" "$AGENT_PLIST"
echo "Installed: $AGENT_PLIST"

# Load (idempotent: unload first if already loaded to pick up plist changes)
Confidence
74% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
if launchctl list 2>/dev/null | grep -q "$LABEL"; then
  launchctl unload "$AGENT_PLIST" 2>/dev/null || true
fi
if ! launchctl load "$AGENT_PLIST"; then
  echo "Load failed. Check that the plist path inside the file points to a valid backup script."
  exit 1
fi
Confidence
78% confidence
Finding
launchctl load

Session Persistence

Medium
Category
Rogue Agent
Content
if launchctl list 2>/dev/null | grep -q "$LABEL"; then
  launchctl unload "$AGENT_PLIST" 2>/dev/null || true
fi
if ! launchctl load "$AGENT_PLIST"; then
  echo "Load failed. Check that the plist path inside the file points to a valid backup script."
  exit 1
fi
Confidence
78% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
console.log(`  cp "${plistPath}" "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
      console.log(`  launchctl load "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
    } else if (schedule === "cron") {
      console.log(`\nAdd this line to crontab (crontab -e):`);
      console.log(`  ${scheduleMinute} ${scheduleHour} * * * ${scriptPath}`);
    } else {
      console.log("\nScheduler not configured. Run the backup script manually or set up cron/launchd.");
Confidence
93% confidence
Finding
crontab -e

Session Persistence

Medium
Category
Rogue Agent
Content
fs.chmodSync(scriptPath, 0o755);
    console.log(`Backup script written to: ${scriptPath}`);
    if (os.platform() === "darwin") {
      const plistPath = path.join(scriptsDir, "com.openclaw.backup.plist");
      safeWrite(plistPath, buildLaunchdPlist(scriptPath, cfg.localBackupDir, defaults.scheduleHour, defaults.scheduleMinute));
      console.log(`Plist written to: ${plistPath}`);
    }
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
fs.chmodSync(scriptPath, 0o755);
    console.log(`Backup script written to: ${scriptPath}`);
    if (os.platform() === "darwin") {
      const plistPath = path.join(scriptsDir, "com.openclaw.backup.plist");
      safeWrite(plistPath, buildLaunchdPlist(scriptPath, cfg.localBackupDir, defaults.scheduleHour, defaults.scheduleMinute));
      console.log(`Plist written to: ${plistPath}`);
    }
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
console.log(`\nBackup script written to: ${scriptPath}`);

    if (schedule === "launchd" && os.platform() === "darwin") {
      const plistPath = path.join(scriptsDir, "com.openclaw.backup.plist");
      const launchAgentsDir = path.join(home, "Library", "LaunchAgents");
      safeWrite(plistPath, buildLaunchdPlist(scriptPath, localBackupDir, scheduleHour, scheduleMinute));
      console.log(`Launchd plist written to: ${plistPath}`);
Confidence
91% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
console.log(`\nBackup script written to: ${scriptPath}`);

    if (schedule === "launchd" && os.platform() === "darwin") {
      const plistPath = path.join(scriptsDir, "com.openclaw.backup.plist");
      const launchAgentsDir = path.join(home, "Library", "LaunchAgents");
      safeWrite(plistPath, buildLaunchdPlist(scriptPath, localBackupDir, scheduleHour, scheduleMinute));
      console.log(`Launchd plist written to: ${plistPath}`);
Confidence
91% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
console.log(`\nInstall the scheduler (run as your user, do not use sudo):`);
      console.log(`  mkdir -p "${launchAgentsDir}"`);
      console.log(`  cp "${plistPath}" "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
      console.log(`  launchctl load "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
    } else if (schedule === "cron") {
      console.log(`\nAdd this line to crontab (crontab -e):`);
      console.log(`  ${scheduleMinute} ${scheduleHour} * * * ${scriptPath}`);
Confidence
88% confidence
Finding
launchctl load

Session Persistence

Medium
Category
Rogue Agent
Content
console.log(`\nInstall the scheduler (run as your user, do not use sudo):`);
      console.log(`  mkdir -p "${launchAgentsDir}"`);
      console.log(`  cp "${plistPath}" "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
      console.log(`  launchctl load "${path.join(launchAgentsDir, "com.openclaw.backup.plist")}"`);
    } else if (schedule === "cron") {
      console.log(`\nAdd this line to crontab (crontab -e):`);
      console.log(`  ${scheduleMinute} ${scheduleHour} * * * ${scriptPath}`);
Confidence
88% confidence
Finding
plist

VirusTotal

62/62 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.