T09 · Insecure Skill Coding Practices
- Location
scripts/hermes-backup.sh:335- Finding
Credential-bearing backup archives are created without enforced access restrictions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/hermes-backup.sh:335Credential-bearing backup archives are created without enforced access restrictions
scripts/hermes-restore.sh:213Restore accepts unauthenticated archives without strict member validation
scripts/hermes-restore.sh:143Forced gateway shutdown can terminate unrelated processes due to broad command-line matching
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.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
"config.yaml"
".env"
"auth.json"
"SOUL.md"
"skills"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
"config.yaml"
".env"
"auth.json"
"SOUL.md"
"skills"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
"config.yaml"
".env"
"auth.json"
"SOUL.md"
"skills"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
"config.yaml"
".env"
"auth.json"
"SOUL.md"
"skills"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# ── Files and directories to INCLUDE (relative to HERMES_HOME) ────────────────
INCLUDE_ITEMS=(
"config.yaml"
".env"
"auth.json"
"SOUL.md"
"skills"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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 ────────────────────────────────────────────────
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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 ────────────────────────────────────────────────
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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 ────────────────────────────────────────────────
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.
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 ──────────────────────────────────────────────────
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
[[ -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 ""
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.
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.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **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
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **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
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **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
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **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
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.
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.
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.