Client Bot Security Audit & Hardening
When to Use
Activate this skill when:
- User asks to "secure all client bots" or "make me the most secure CTO"
- Auditing security posture of deployed Telegram bots
- Inventorying which bots run where and with what secrets
- Checking SSH key hygiene for bot-hosting fleet nodes
- Setting up a bot provisioning pipeline
- Reviewing or creating the bot-provisioning-ledger.json
Bot Discovery & Inventory
1. Find Bot Avatars
Bot avatars in the workspace reveal which Telegram bots exist:
ls -la ~/clawd/assets/agent-avatars/
# Pattern: <name>-<handle>.jpg
# e.g. priva-Privanotifybot.jpg → @Privanotifybot
2. Find Bot Projects
Search the workspace for bot-related projects:
ls ~/clawd/projects/ | grep -iE '(bot|telegram|notify|agent)'
3. Find Bot Configs & Secrets
Three layers of secret storage:
.weblyfe-secrets/— central secrets vault (appie-1 only)- Hermes
.envfiles — per-node (appie-2:/root/.hermes/.env) - OpenClaw config — (eugi:
/root/.openclaw/openclaw.json)
# Central vault
ls -la ~/.weblyfe-secrets/
# → bot-provisioning-ledger.json (token_ref map)
# → bot-provisioning-pool.env (raw tokens for free pool)
# → telegram-bot.env (current bot token for this agent)
# → .env (all other API keys)
# Fleet node Hermes
ssh <user>@<tailscale_ip> "cat /root/.hermes/.env | grep -iE 'BOT|TOKEN'"
# Fleet node OpenClaw
ssh <user>@<tailscale_ip> "cat /root/.openclaw/openclaw.json"
4. Bot Topology Map
Document per bot:
| Field | Example |
|---|---|
| name | Appie-3 CTO |
| handle | @eppieweblyfebot |
| token_ref | TELEGRAM_BOT_TOKEN (in telegram-bot.env) |
| host | appie-1 (this Mac Mini) |
| gateway | Hermes |
| status | active / assigned / free / retired |
The bot-provisioning-ledger.json tracks:
{
"name": "Appie Doctor",
"handle": "@weblyfebot",
"token_ref": "APPIE_DOCTOR_BOT_TOKEN",
"status": "assigned",
"box": "mac-mini (appie-1)",
"sale": null,
"assigned_at": "2026-06-11",
"notes": "..."
}
5. Gateways & Running Processes
Check what's running on each fleet node:
# Hermes gateway detection
ssh <host> "ps aux | grep -iE '(gateway|hermes)' | grep -v grep"
# → /usr/local/lib/hermes-agent/venv/bin/python -m hermes_cli.main gateway run --replace
# OpenClaw gateway detection
ssh <host> "ps aux | grep -iE '(openclaw|openclaw-gateway)' | grep -v grep"
# → openclaw-gateway
# Open ports
ssh <host> "ss -tlnp" # Linux
# Hermes: varies (gateway port in config)
# OpenClaw: typically 18789 (HTTP API) + 18791 (internal)
SSH Key Audit Procedure
📘 Reference: See
references/ssh-connectivity-troubleshooting.mdfor a systematic SSH failure diagnosis flow (macOS vs Linux, rate-limiting avoidance, Tailscale SSH quirks, SSH policy inspection, verbose debugging, and common failure modes).
1. Inventory Authorized Keys
for host in "<user>@<ip1>" "<user>@<ip2>"; do
echo "=== $host ==="
ssh -o ConnectTimeout=5 -o BatchMode=yes -o StrictHostKeyChecking=no \
-i "$HOME/.ssh/<key>" "$host" \
"cat /root/.ssh/authorized_keys | awk '{print \$3}'"
done
This reveals:
- How many keys are authorized (baseline for changes)
- Who has access (the comment field = identity)
- Stale/decommissioned keys
2. Check for Deploy Keys
ssh <host> "ls -la /root/.ssh/ | grep -v authorized_keys | grep -v known_hosts"
Deploy keys (for CI/CD or service accounts) should be in separate files with clear filenames.
3. Audit SSH Config
ssh <host> "cat /root/.ssh/config"
Check for:
PasswordAuthentication noPubkeyAuthentication yes- No wildcard
Host *that exposes sensitive hosts
4. Root Login Assessment
Determine if the node allows direct root SSH. If so, document and flag for hardening:
ssh <host> "grep -i 'permitrootlogin\|passwordauthentication' /etc/ssh/sshd_config"
Bot Token Security
Where Tokens Live
| Location | Risk | Mitigation |
|---|---|---|
~/.weblyfe-secrets/ (appie-1) |
Medium (local machine compromise) | chmod 600, no git track |
/root/.hermes/.env (appie-2) |
Medium (VPS compromise) | chmod 600, root-only read |
| OpenClaw config (eugi) | Medium (VPS compromise) | chmod 600 on config dir |
| Bot provisioning pool | High (bulk token leak) | Never echo to chat/logs |
Token Discipline Rules
- Never echo token values to chat, logs, or commits
- Never put tokens in
package.json,bot.py, or any tracked file - Always chmod 600 on .env files
- Always use
token_refin the ledger, not raw tokens - Token rotation: rotate on each bot reassignment or security incident
- Provisioning: new bots → pool tokens → assign in ledger → point env → test → activate
Gitleaks for Token Detection
# Scan all project dirs for leaked tokens
gitleaks detect --source ~/clawd/projects --no-git --config ~/.gitleaks.toml --verbose
Bot Lifecycle
free → assigned → active → retired
- free: token in provisioning pool, no box assigned
- assigned: token linked to a box/env, not yet tested
- active: confirmed running, serving users
- retired: token revoked, bot removed, ledger archived
Secrets Map
Maintain a secrets map that documents:
- Secret: env var name
- Location: which file(s) and node(s)
- Access: which users/processes can read it
- Rotation: last rotated, rotation policy
- Scope: which bot(s) depend on it
Format:
| Secret | Location | Access | Scope |
|--------|----------|--------|-------|
| TELEGRAM_BOT_TOKEN (Appie-3) | `~/.weblyfe-secrets/telegram-bot.env` | root@appie-1 | Appie-3 CTO |
| TELEGRAM_BOT_TOKEN (Appie-2) | `/root/.hermes/.env` | root@appie-2 | Appie-2 gateway |
Client Bot Security Checklist
Run this checklist for each new client bot deployment:
- Bot token in
.weblyfe-secrets/bot-provisioning-pool.env(not tracked) - Bot registered in
bot-provisioning-ledger.jsonwith token_ref - Status set to
assigned(with box, sale, assigned_at) - SSH access to host verified (key + user)
- authorized_keys reviewed (only current keys)
- .env file has chmod 600
- Gateway verified running (Hermes or OpenClaw)
- Bot responds to /start (telegram smoke test)
- Gitleaks scan passes on project dir
- Dep audit clean (npm audit / safety check)
- Tailscale ACL permits bot-to-user traffic
Pitfalls
- spark-atlas SSH key broken: Key
id_ed25519_sparkfor root@100.69.197.43 returnsPermission denied. May need a different user/key. Don't assume all fleet nodes are reachable. - Bot provisioning pool leak: The pool env has 5 unassigned bot tokens. If leaked, all 5 are compromised. Guard with chmod 600.
- OpenClaw vs Hermes configs are different: OpenClaw stores tokens in
openclaw.json(JSON), not.env. Know which gateway runs on which node before looking. - Ghost nodes return: Nodes that were offline >30d may have different SSH keys when they come back. Verify before re-adding to active scan.
- authorized_keys drift: Manual SSH key additions by other agents/users can go undocumented. Compare against a known-good baseline.