soul-guardian

Automation

Drift detection + baseline integrity guard for agent workspace files with automatic alerting support

Install

openclaw skills install soul-guardian

soul-guardian 👻

Protects your agent's core files (SOUL.md, AGENTS.md, etc.) from unauthorized changes with automatic detection, restoration, and user alerting.

Operational Notes

  • Required runtime: python3
  • Optional runtime: openclaw for cron integration, launchctl for macOS scheduling, bash for the demo helper
  • Side effects: can auto-restore protected files to their approved baseline and writes audit/quarantine state locally
  • Network behavior: none by default
  • Trust model: any scheduling is opt-in, but restore mode intentionally overwrites drifted files

Release Artifact Verification

For standalone installs, verify the signed release manifest before trusting SKILL.md, skill.json, or the archive. The skill.json file is the package metadata/SBOM source, and the release pipeline signs checksums.json with the ClawSec release key.

set -euo pipefail

SKILL_NAME="soul-guardian"
VERSION="0.0.6"
REPO="prompt-security/clawsec"
TAG="${SKILL_NAME}-v${VERSION}"
BASE="https://github.com/${REPO}/releases/download/${TAG}"
ZIP_NAME="${SKILL_NAME}-v${VERSION}.zip"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

RELEASE_PUBKEY_SHA256="711424e4535f84093fefb024cd1ca4ec87439e53907b305b79a631d5befba9c8"

curl -fsSL "$BASE/checksums.json" -o "$TMP_DIR/checksums.json"
curl -fsSL "$BASE/checksums.sig" -o "$TMP_DIR/checksums.sig"
curl -fsSL "$BASE/signing-public.pem" -o "$TMP_DIR/signing-public.pem"
curl -fsSL "$BASE/$ZIP_NAME" -o "$TMP_DIR/$ZIP_NAME"
curl -fsSL "$BASE/SKILL.md" -o "$TMP_DIR/SKILL.md"
curl -fsSL "$BASE/skill.json" -o "$TMP_DIR/skill.json"

ACTUAL_PUBKEY_SHA256="$(openssl pkey -pubin -in "$TMP_DIR/signing-public.pem" -outform DER | shasum -a 256 | awk '{print $1}')"
if [ "$ACTUAL_PUBKEY_SHA256" != "$RELEASE_PUBKEY_SHA256" ]; then
  echo "ERROR: signing-public.pem fingerprint mismatch" >&2
  exit 1
fi

openssl base64 -d -A -in "$TMP_DIR/checksums.sig" -out "$TMP_DIR/checksums.sig.bin"
openssl pkeyutl -verify -rawin -pubin \
  -inkey "$TMP_DIR/signing-public.pem" \
  -sigfile "$TMP_DIR/checksums.sig.bin" \
  -in "$TMP_DIR/checksums.json" >/dev/null

hash_file() {
  if command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$1" | awk '{print $1}'
  else
    sha256sum "$1" | awk '{print $1}'
  fi
}

verify_manifest_file() {
  asset="$1"
  path="$2"
  expected="$(jq -r --arg asset "$asset" '.files[$asset].sha256 // empty' "$TMP_DIR/checksums.json")"
  if [ -z "$expected" ]; then
    echo "ERROR: checksums.json missing $asset" >&2
    exit 1
  fi
  actual="$(hash_file "$path")"
  if [ "$actual" != "$expected" ]; then
    echo "ERROR: checksum mismatch for $asset" >&2
    exit 1
  fi
}

expected_archive="$(jq -r '.archive.sha256 // empty' "$TMP_DIR/checksums.json")"
if [ -z "$expected_archive" ]; then
  echo "ERROR: checksums.json missing archive.sha256" >&2
  exit 1
fi
actual_archive="$(hash_file "$TMP_DIR/$ZIP_NAME")"
if [ "$actual_archive" != "$expected_archive" ]; then
  echo "ERROR: archive checksum mismatch" >&2
  exit 1
fi

verify_manifest_file "SKILL.md" "$TMP_DIR/SKILL.md"
verify_manifest_file "skill.json" "$TMP_DIR/skill.json"

echo "Signed release manifest, archive, SKILL.md, and skill.json verified."

Only install or extract the archive after this verification succeeds.

Quick Start (3 Steps)

Step 1: Initialize baselines

cd ~/.openclaw/workspace
python3 skills/soul-guardian/scripts/soul_guardian.py init --actor setup --note "initial baseline"

Step 2: Enable monitoring

python3 skills/soul-guardian/scripts/soul_guardian.py enable-monitoring

This shows you how to add monitoring to your workflow.

Step 3: Add to HEARTBEAT.md (Recommended)

Add this to your HEARTBEAT.md for automatic monitoring:

## Soul Guardian Check
- Run `python3 skills/soul-guardian/scripts/soul_guardian.py check --actor heartbeat --output-format alert`
- If any output is produced, relay it to the user immediately as a security alert

That's it! Soul Guardian will now:

  • ✅ Detect unauthorized changes to protected files
  • ✅ Auto-restore SOUL.md and AGENTS.md to approved baseline
  • ✅ Alert you when drift is detected and handled

What it protects (default policy)

FileModeAction on drift
SOUL.mdrestoreAuto-restore + alert
AGENTS.mdrestoreAuto-restore + alert
USER.mdalertAlert only
TOOLS.mdalertAlert only
IDENTITY.mdalertAlert only
HEARTBEAT.mdalertAlert only
MEMORY.mdalertAlert only
memory/*.mdignoreIgnored

Commands

Check for drift (with alert output)

python3 skills/soul-guardian/scripts/soul_guardian.py check --output-format alert
  • Silent if no drift
  • Outputs human-readable alert if drift detected
  • Perfect for heartbeat integration

Watch mode (continuous monitoring)

python3 skills/soul-guardian/scripts/soul_guardian.py watch --interval 30

Runs continuously, checking every 30 seconds.

Approve intentional changes

python3 skills/soul-guardian/scripts/soul_guardian.py approve --file SOUL.md --actor user --note "intentional update"

View status

python3 skills/soul-guardian/scripts/soul_guardian.py status

Verify audit log integrity

python3 skills/soul-guardian/scripts/soul_guardian.py verify-audit

Alert Format

When drift is detected, the --output-format alert produces output like:

==================================================
🚨 SOUL GUARDIAN SECURITY ALERT
==================================================

📄 FILE: SOUL.md
   Mode: restore
   Status: ✅ RESTORED to approved baseline
   Expected hash: abc123def456...
   Found hash:    789xyz000111...
   Diff saved: /path/to/patches/drift.patch

==================================================
Review changes and investigate the source of drift.
If intentional, run: soul_guardian.py approve --file <path>
==================================================

This output is designed to be relayed directly to the user in TUI/chat.


Security Model

What it does:

  • Detects filesystem drift vs approved baseline (sha256)
  • Produces unified diffs for review
  • Maintains tamper-evident audit log with hash chaining
  • Refuses to operate on symlinks
  • Uses atomic writes for restores

What it doesn't do:

  • Cannot prove WHO made a change (actor is best-effort metadata)
  • Cannot protect if attacker controls both workspace AND state directory
  • Is not a substitute for backups

Recommendation: Store state directory outside workspace for better resilience.


Demo

Run the full demo flow to see soul-guardian in action:

bash skills/soul-guardian/scripts/demo.sh

This will:

  1. Verify clean state (silent check)
  2. Inject malicious content into SOUL.md
  3. Run heartbeat check (produces alert)
  4. Show SOUL.md was restored

Troubleshooting

"Not initialized" error: Run init first to set up baselines.

Drift keeps happening: Check what's modifying your files. Review the audit log and patches.

Want to approve a change: Run approve --file <path> after reviewing the change.