Back to skill

Security audit

Personality Backup

Security checks for vulnerabilities and agentic risk

Overview

This backup skill appears purpose-aligned, but it handles highly sensitive agent data with unsafe defaults, email delivery, and risky scheduling guidance.

Review carefully before installing. Use local-only delivery unless email is truly required, disable secrets and memory backup by default, avoid the provided crontab command, and do not run it with broad workspace paths until temporary-file handling, password handling, and confirmation safeguards are improved.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (3)

T06 · System Persistence

Error
Location
SKILL.md:67
Finding
Recurring Cron Persistence Overwrites the Existing User Crontab<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:67-72` **Vulnerability Type**: Unsafe scheduled-task persistence **Risk Level**: High ### Vulnerable Code ```bash ### Set up daily cron ```bash echo "0 3 * * * bash $(pwd)/scripts/backup.sh /path/to/backup-config.json" | crontab - ``` ``` ### Technical Analysis The documented command installs a cron entry that executes the backup script every day at 03:00, creating cross-session persistence. Automated scheduling is relevant to the declared backup functionality, but this implementation is not least-impact: - `crontab -` replaces the user's entire existing crontab instead of adding only the backup entry. - No confirmation, backup, duplicate detection, or rollback mechanism is provided. - The script path produced by `$(pwd)` is inserted into the cron command without robust shell quoting. - The persistent task repeatedly accesses highly sensitive personality files, memory, configuration, projects, scripts, and potentially the complete secrets directory. - If the Skill directory or referenced configuration becomes writable by another party, the scheduled task becomes a recurring execution or data-exfiltration channel under the affected user's account. The persistence is disclosed rather than hidden, but it still exceeds the minimum safe implementation needed for optional backup scheduling because it can destroy unrelated scheduled tasks and does not protect the integrity of the files executed by cron. ### Attack Path 1. A user follows the documented cron setup command. 2. The piped input replaces the user's complete crontab with the single backup entry. 3. Any unrelated cron jobs previously configured for that user are removed. 4. Cron subsequently invokes `scripts/backup.sh` every day under the user's account. 5. If an attacker can later modify the Skill directory, backup configuration, or referenced script, the attacker-controlled content is executed automatically on the next scheduled run. ...[truncated 578 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Make automated scheduling explicitly optional and require informed user confirmation. - Preserve existing jobs instead of replacing the complete crontab. - Add a uniquely marked, idempotent entry only if it does not already exist. - Back up the current crontab before changing it and document a precise uninstall procedure. - Resolve paths before installation and safely quote or reject paths containing newlines or other unsafe characters. - Verify that the scheduled script and configuration are owned by the intended user and are not writable by group members or other users. - Prefer a dedicated user-level scheduler unit with explicit permissions, logging, and lifecycle controls. - Document that the scheduled process repeatedly reads sensitive data and identify the exact delivery destination. A safer installation flow should preserve existing entries, for example by collecting `crontab -l` output, checking for a unique marker, and appending one validated entry rather than piping a replacement crontab directly. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/backup.sh:20
Finding
Sensitive Backup Data Uses Predictable Shared Temporary Paths<![CDATA[ ## Vulnerability Details **File Location**: `scripts/backup.sh:20-47` **Vulnerability Type**: Unsafe temporary-file and temporary-directory handling **Risk Level**: High ### Vulnerable Code ```bash BACKUP_DIR="/tmp/agent-backup-$$" ARCHIVE_NAME="backup-$(date +%Y-%m-%d).7z" ARCHIVE_PATH="/tmp/$ARCHIVE_NAME" trap "rm -rf $BACKUP_DIR $ARCHIVE_PATH" EXIT echo "$(date) — Starting personality backup..." mkdir -p "$BACKUP_DIR" ``` Sensitive content is then copied into that shared temporary directory: ```bash # 3. Secrets if [ "$CFG_BACKUP_SECRETS" = "true" ] && [ -d "$CFG_SECRETS_DIR" ]; then echo "Copying secrets..." mkdir -p "$BACKUP_DIR/secrets" cp -r "$CFG_SECRETS_DIR"/* "$BACKUP_DIR/secrets/" 2>/dev/null || true fi ``` ### Technical Analysis The script stages plaintext personality data, memory, configuration, projects, scripts, and secrets beneath `/tmp` before encryption. It constructs paths from the process ID and current date rather than using an atomic secure temporary-file facility. The implementation has the following weaknesses: - `/tmp/agent-backup-$$` is predictable to local processes that can observe or anticipate the backup process. - `/tmp/backup-YYYY-MM-DD.7z` is predictable and shared by every run on the same day. - Concurrent runs use the same archive path and can corrupt, overwrite, or deliver the wrong archive. - The script does not set a restrictive `umask` before creating directories, copied data, or the encrypted archive. - Resulting accessibility depends partly on inherited source permissions and the user's current `umask`, rather than an enforced private backup policy. - Predictable pre-existing filesystem objects can cause denial of service or potentially redirect archive operations, depending on 7z's handling of the object. - The staging area contains plaintext data until the exit trap runs. Abrupt termination that bypasses normal trap processing can leave sensitive material behind. - The cleanup trap is constr ...[truncated 1331 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Set `umask 077` before creating any staging data or archive. - Create the staging directory atomically with `mktemp -d`, preferably under a user-private runtime directory. - Allocate the archive path securely instead of using only the current date. - Refuse to operate on pre-existing, symbolic-link, or non-regular archive paths. - Use a cleanup function with properly quoted variables: ```bash cleanup() { rm -rf -- "$BACKUP_DIR" rm -f -- "$ARCHIVE_PATH" } trap cleanup EXIT INT TERM HUP ``` - Explicitly apply mode `0700` to the staging directory and `0600` to the archive. - Prevent concurrent runs with a private lock file or scheduler-level locking. - Minimize plaintext staging; where practical, stream selected content directly into an encrypted archive. - Disable `backup_secrets` by default and require explicit user opt-in. - Validate cleanup success and warn the user if sensitive temporary material cannot be removed. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/backup.sh:86
Finding
Archive Encryption Password Is Exposed Through Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/backup.sh:86-89` **Vulnerability Type**: Sensitive credential exposure in command-line arguments **Risk Level**: High ### Vulnerable Code ```bash # 9. Create encrypted archive echo "Creating encrypted 7z archive..." 7z a -t7z -mhe=on -p"$CFG_PASSWORD" "$ARCHIVE_PATH" "$BACKUP_DIR"/* > /dev/null SIZE=$(du -sh "$ARCHIVE_PATH" | cut -f1) ``` The password originates from the configured password file: ```python if pw_file and os.path.isfile(pw_file): with open(pw_file) as f: field = c.get("password_field", "Password") if field: for line in f: if line.startswith(f"{field}:"): password = line.split(":", 1)[1].strip() break ``` ### Technical Analysis The password is passed to 7z as part of the `-p` command-line argument. Command-line arguments can be visible to process-monitoring tools and, depending on operating-system process visibility settings, other local users. Monitoring agents, diagnostic tooling, shell wrappers, audit systems, and privileged processes may also record the complete invocation. Header encryption (`-mhe=on`) protects archive metadata but does not mitigate disclosure of the encryption key itself. Once the password is captured, any locally stored or emailed archive protected by that password can be decrypted. The script also does not verify that `CFG_PASSWORD` is non-empty before copying sensitive files and invoking 7z. A missing file, unmatched field, or empty password therefore does not trigger a deliberate fail-closed validation step. ### Attack Path 1. The user or cron task starts the backup script. 2. `parse_config.py` reads the archive password and emits it into the shell variable `CFG_PASSWORD`. 3. The shell starts 7z with the password embedded in its argument list. 4. A local observer, monitoring system, or privileged process captures the 7z command line while it is running. 5. The ...[truncated 618 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use an encryption mechanism that accepts the password through a protected file descriptor, standard input, or another interface that does not expose it in the process argument list. - If 7z cannot meet this requirement securely in the target environment, use a backup/encryption tool designed for noninteractive secret input. - Validate the password before creating the staging directory: ```bash if [ -z "${CFG_PASSWORD:-}" ]; then echo "ERROR: A non-empty backup password is required." >&2 exit 1 fi ``` - Enforce restrictive permissions on the password file and verify that it is a regular file owned by the expected user. - Avoid exporting the password into child-process environments unnecessarily. - Do not log commands containing credentials, and review process-monitoring or auditing systems for accidental argument capture. - Support key rotation and document re-encryption of retained archives after suspected password exposure. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents this skill as a backup creation and management tool with encryption and delivery features. The supplied code does not back up, copy, compress, encrypt, transmit, or schedule anything. It only loads configuration values and writes a RESTORE.md file containing human-readable restoration instructions. While the generated document references backups and cron re-enablement, those are just text output, not implemented behavior. This is a materially different primary purpose from the declared backup/encryption/delivery functionality.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill description advertises backup of secrets, identity files, and memory with email delivery, but it does not prominently warn that highly sensitive data may be archived and transmitted off-host. Users may invoke it without understanding the sensitivity or the exfiltration implications, increasing the risk of unintended disclosure.

Credential Access

High
Category
Privilege Escalation
Content
```json
{
  "password_file": "/home/jan/.openclaw/secrets/backup-password.txt",
  "password_field": "Password",
  "delivery": "email",
  "email": {
Confidence
90% confidence
Finding
The skill is explicitly designed to access a password file and optionally bundle the secrets directory into backups. In context, this is credential handling rather than accidental mention, but it is still dangerous because it centralizes and processes authentication material alongside a workflow that can email archives off-host.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill describes operations that require access to environment variables and writing files, but it declares no explicit tool scope or permission boundaries. In a backup skill that handles secrets, missing capability scoping increases the chance of overbroad execution or silent access to sensitive data without clear user understanding.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: personality-backup
description: Create encrypted backups of agent personality files, memory, config, secrets, and projects. Use when the agent needs to set up, run, or manage automated backups of its workspace and identity files. Supports configurable backup targets, AES-256 encryption via 7-zip, and delivery via email (SMTP) or local storage.
---

# Personality Backup
Confidence
88% confidence
Finding
The skill promotes automated backup of personality, memory, config, and workspace data, which creates durable copies of agent state and identity information. This persistence expands the attack surface by preserving sensitive context longer than necessary and making it easier to restore, clone, or inspect the agent's prior state.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The invocation text is broad enough that the skill could be triggered in many contexts involving workspace or identity management, even when backup of secrets was not specifically requested. Because the skill targets memory, config, secrets, and projects, accidental activation could lead to unnecessary collection, archival, or transmission of highly sensitive data.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The cron example sets up unattended recurring backups of sensitive data without warning about persistence, rotation, destination trust, or repeated transmission of secrets. Automating this process can normalize continuous collection and delivery of confidential material, magnifying damage from misconfiguration or account compromise.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This script explicitly collects highly sensitive material including secrets, memory, config, and projects, packages it, and can deliver it via email or local storage. Even though encryption is used, there is no explicit consent, interactive warning, destination validation, or minimization control at the point of execution, so a misconfigured or socially engineered run can silently exfiltrate an agent's identity and credentials.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This script automatically emails a backup archive containing highly sensitive material described by the skill as personality files, memory, config, secrets, and projects, yet it provides no user-facing warning, confirmation, or explicit disclosure at the point of transmission. In this skill context, silent exfiltration via SMTP is especially dangerous because the archive leaves the local trust boundary and may be sent to a misconfigured, attacker-controlled, or unintended recipient without the operator realizing it.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script reads backup and SMTP credentials from files or environment variables and then prints them as shell variable assignments, exposing secrets to any caller, wrapper script, logs, process captures, or debugging output that consumes stdout. In the context of a backup skill that explicitly handles personality data, memory, config, and secrets, propagating credentials through plaintext shell output materially increases the chance of credential leakage and downstream compromise of backup stores or email infrastructure.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This code performs a file write to a user-supplied output path, which can overwrite existing content, but it provides no confirmation prompt, warning comment, or user-facing disclosure beyond a generic success message. For code files, file writes should have some visible disclosure unless the action is clearly explained as part of the skill behavior.