Back to skill

Security audit

hermes-backup-restore

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Hermes backup and restore skill, but it handles secrets and can restore behavior-changing files from unvalidated archives.

Install only if you understand that backups can contain API keys, auth tokens, sessions, memories, profiles, skills, hooks, plugins, and other private Hermes data. Store archives like credentials, avoid shared locations, prefer encrypted transfer, inspect archives before restoring, and restore only archives you created and trust. Use --dry-run first, be cautious with --force and -t/--target, and expect restore to overwrite persistent Hermes behavior and configuration.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hermes-backup.sh:335
Finding

Credential-bearing backup archives are created without enforced access restrictions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/hermes-restore.sh:213
Finding

Restore accepts unauthenticated archives without strict member validation

Content
View full analysis
/dev/null; then echo "ERROR: Archive is corrupt or not a valid gzip tar: $BACKUP_FILE" >&2 exit 1 fi echo " ✓ Archive OK" ``` ```bash STAGING=$(mktemp -d "${TMPDIR:-/tmp}/hermes-restore.XXXXXX") trap 'rm -rf "$STAGING"' EXIT tar -xzf "$BACKUP_FILE" -C "$STAGING" # Find the top-level directory in the archive (should be hermes-backup/) STAGE_ROOT=$(find "$STAGING" -maxdepth 1 -type d | tail -1) if [[ -z "$STAGE_ROOT" ]] || [[ "$STAGE_ROOT" == "$STAGING" ]]; then echo "ERROR: Could not find expected directory structure in archive" >&2 echo "Archive contents:" >&2 tar -tzf "$BACKUP_FILE" | head -20 >&2 exit 1 fi ``` ```bash if [[ "$MERGE" == "true" ]]; then rsync -a --info=name0 --ignore-existing "$STAGE_ROOT/" "$HERMES_HOME/" \ --exclude "BACKUP_MANIFEST.json" else rsync -a --info=name0 "$STAGE_ROOT/" "$HERMES_HOME/" \ --exclude "BACKUP_MANIFEST.json" fi ``` ### Technical Analysis The operation described as archive integrity verification only confirms that the input can be parsed as a gzip-compressed tar archive. It does not establish the archive's authenticity or verify that its members match a trusted manifest. Before extraction, the script does not explicitly reject: - Absolute member paths. - Paths containing `..` traversal components. - Symbolic links or hard links. - Device nodes, FIFOs, or other special file types. - Multiple or unexpected top-level directories. - Files outside the documented Hermes backup allowlist. - Files not declared in `BACKUP_MANIFEST.json`. The manifest is optional and is only parsed to display metadata. It contains no verified hashes or signature and is not compared with the extracted files. A ...[truncated 2260 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hermes-restore.sh:143
Finding

Forced gateway shutdown can terminate unrelated processes due to broad command-line matching

Content
View full analysis
/dev/null 2>&1; then GATEWAY_PIDS=$(pgrep -f "hermes.*gateway\|hermes_cli\.main\|hermes-agent/venv" 2>/dev/null | tr '\n' ' ') if [[ -n "$GATEWAY_PIDS" ]]; then echo "⚠ WARNING: Hermes gateway is running (PIDs: $GATEWAY_PIDS)" echo " Restoring SQLite databases while the gateway is live will CORRUPT them." echo " The gateway holds file handles and will overwrite restored databases." echo "" if [[ "$FORCE" == "true" ]]; then echo " --force given, stopping gateway automatically..." for pid in $GATEWAY_PIDS; do kill "$pid" 2>/dev/null || true done sleep 2 for pid in $GATEWAY_PIDS; do kill -9 "$pid" 2>/dev/null || true done ``` ### Technical Analysis Stopping an active Hermes gateway before replacing SQLite databases is necessary for the declared restore functionality. The implementation, however, identifies gateway processes using broad full-command-line expressions. The alternatives `hermes_cli.main` and `hermes-agent/venv` can match Hermes-related processes that are not the gateway. The expression can also match an unrelated process whose arguments happen to contain one of these strings. After sending the initial termination signal, the script sleeps for two seconds and then sends `SIGKILL` to every originally captured PID. It does not check whether the process is still alive, whether the PID has been reused, whether the executable belongs to Hermes, or whether it is specifically the gateway process. ### Attack Path 1. A legitimate unrelated process has a command line matching `hermes_cli.main`, `hermes-agent/venv`, or the broad `hermes.*gateway` expression. 2. The user invokes resto ...[truncated 1006 chars]
Remediation
View remediation
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented behavior and the described backup scope do not cleanly match: the skill claims a specific purpose but also references backing up additional resources, and restore behavior is not fully represented in the provided content. In backup/restore tooling, scope ambiguity is dangerous because users may unknowingly archive or restore more data than expected, including sensitive or operationally critical files.

Content

No source excerpt is available for this finding.

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 · scripts/hermes-backup.sh (reported line 95)May include surrounding context.

sh
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
  "config.yaml"
  ".env"
  "auth.json"
  "SOUL.md"
  "skills"

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 · scripts/hermes-restore.sh (reported line 198)May include surrounding context.

sh
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
  "config.yaml"
  ".env"
  "auth.json"
  "SOUL.md"
  "skills"

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 · scripts/hermes-restore.sh (reported line 201)May include surrounding context.

sh
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
  "config.yaml"
  ".env"
  "auth.json"
  "SOUL.md"
  "skills"

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 · scripts/hermes-restore.sh (reported line 338)May include surrounding context.

sh
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
  "config.yaml"
  ".env"
  "auth.json"
  "SOUL.md"
  "skills"

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 · scripts/hermes-restore.sh (reported line 379)May include surrounding context.

sh
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
  "config.yaml"
  ".env"
  "auth.json"
  "SOUL.md"
  "skills"

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 · scripts/hermes-restore.sh (reported line 202)May include surrounding context.

sh
BACKUP_TS="${BACKUP_TS:-$(date +%Y%m%d_%H%M%S)}"
  EXISTING_ENV_BACKUP="$HERMES_HOME/.env.pre-restore.$BACKUP_TS"
  cp -a "$HERMES_HOME/.env" "$EXISTING_ENV_BACKUP"
  echo "► Backed up existing .env → $EXISTING_ENV_BACKUP"
fi

# ── Extract archive to staging ────────────────────────────────────────────────

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 · scripts/hermes-restore.sh (reported line 354)May include surrounding context.

sh
BACKUP_TS="${BACKUP_TS:-$(date +%Y%m%d_%H%M%S)}"
  EXISTING_ENV_BACKUP="$HERMES_HOME/.env.pre-restore.$BACKUP_TS"
  cp -a "$HERMES_HOME/.env" "$EXISTING_ENV_BACKUP"
  echo "► Backed up existing .env → $EXISTING_ENV_BACKUP"
fi

# ── Extract archive to staging ────────────────────────────────────────────────

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 · scripts/hermes-restore.sh (reported line 388)May include surrounding context.

sh
BACKUP_TS="${BACKUP_TS:-$(date +%Y%m%d_%H%M%S)}"
  EXISTING_ENV_BACKUP="$HERMES_HOME/.env.pre-restore.$BACKUP_TS"
  cp -a "$HERMES_HOME/.env" "$EXISTING_ENV_BACKUP"
  echo "► Backed up existing .env → $EXISTING_ENV_BACKUP"
fi

# ── Extract archive to staging ────────────────────────────────────────────────

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

The script accepts a user-controlled target path and later removes lock files under that path without validating that HERMES_HOME is a safe directory. If the script is run with elevated privileges or pointed at an attacker-chosen location, it can delete arbitrary files matching those names outside the intended Hermes home, which is a path-manipulation risk in a restore tool.

Content

Scanner excerpt · scripts/hermes-restore.sh (reported line 302)May include surrounding context.

sh
fi
done
# Also clean lock files that gate SQLite access
rm -f "$HERMES_HOME/state.db.repair.lock" "$HERMES_HOME/state.db.fts_rebuild.lock" 2>/dev/null || true
echo "  ✓ Stale WAL/SHM and repair locks cleaned"

# ── Verify SQLite integrity ──────────────────────────────────────────────────

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/hermes-restore.sh (reported line 342)May include surrounding context.

sh
[[ -f "$HERMES_HOME/auth.json" ]] && chmod 600 "$HERMES_HOME/auth.json" 2>/dev/null || true

# Skills should be readable
[[ -d "$HERMES_HOME/skills" ]] && chmod -R u+rwX,go+rX "$HERMES_HOME/skills" 2>/dev/null || true

# ── Summary ───────────────────────────────────────────────────────────────────
echo ""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises and instructs use of shell scripts but does not declare any tool scope or allowed-tools boundary. In an agent setting, missing permission declarations can cause the agent to invoke shell access more broadly than intended, increasing the chance of unsafe execution against the local system.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly handles secrets, auth material, sessions, memories, and profile data, yet the usage documentation does not prominently warn that the produced archive will contain highly sensitive data or that restore can overwrite existing state. This creates a real risk of credential leakage, accidental transfer of private data, or destructive restoration into the wrong environment.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- **Manifest**: Every backup includes a JSON manifest with metadata (hostname, user, Hermes version, file list)
- **Profile-aware**: Back up and restore individual profiles
- **Integrity verification**: Restored databases are checked with `PRAGMA integrity_check`
- **Permission hardening**: Config and secrets set to `chmod 600` after restore
- **Dry run**: Both scripts support `--dry-run` for safe preview

## Requirements

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/hermes-restore.sh (reported line 337)May include surrounding context.

sh
- **Manifest**: Every backup includes a JSON manifest with metadata (hostname, user, Hermes version, file list)
- **Profile-aware**: Back up and restore individual profiles
- **Integrity verification**: Restored databases are checked with `PRAGMA integrity_check`
- **Permission hardening**: Config and secrets set to `chmod 600` after restore
- **Dry run**: Both scripts support `--dry-run` for safe preview

## Requirements

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/hermes-restore.sh (reported line 338)May include surrounding context.

sh
- **Manifest**: Every backup includes a JSON manifest with metadata (hostname, user, Hermes version, file list)
- **Profile-aware**: Back up and restore individual profiles
- **Integrity verification**: Restored databases are checked with `PRAGMA integrity_check`
- **Permission hardening**: Config and secrets set to `chmod 600` after restore
- **Dry run**: Both scripts support `--dry-run` for safe preview

## Requirements

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/hermes-restore.sh (reported line 339)May include surrounding context.

sh
- **Manifest**: Every backup includes a JSON manifest with metadata (hostname, user, Hermes version, file list)
- **Profile-aware**: Back up and restore individual profiles
- **Integrity verification**: Restored databases are checked with `PRAGMA integrity_check`
- **Permission hardening**: Config and secrets set to `chmod 600` after restore
- **Dry run**: Both scripts support `--dry-run` for safe preview

## Requirements

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This backup skill intentionally archives highly sensitive material including secrets, auth data, sessions, memories, and profiles, but it does not warn the operator that the resulting tar.gz may contain credentials and private data in plaintext-equivalent form. In the context of a portable backup tool, that omission increases the chance of accidental disclosure through insecure storage, transfer, or sharing of the archive.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description says the skill backs up config, secrets, skills, sessions, memories, cron, and profiles, but the script documentation and include list also back up kanban, soul/SOUL.md, hooks, skins, plugins, widgets, pets, platforms, and bin. This broadens the operational scope beyond what the manifest advertises, creating a semantic mismatch about what Hermes data is collected.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes backing up Hermes Agent data, while the script’s --full mode explicitly includes the hermes-agent source code. Source code backup is not represented in the manifest description and is materially different from backing up user data/configuration.

Content

No source excerpt is available for this finding.