Autonomous Linux server security management. Runs full audit at 1 AM IST nightly via cron. Covers system hardening, CVE scanning, user auditing, SSH config,...
---
name: linux-security-guardian
description: Autonomous multi-client Linux server security management via SSH MCP. Runs full audit at 1 AM IST nightly via cron. Iterates over all clients and their server fleets. Covers system hardening, CVE scanning (CISA KEV + OSV.dev + NVD API), user auditing, SSH config, firewall rules, running services, file permissions, log analysis, SSL certs, and kernel parameters. Non-breaking actions auto-applied. Critical patches and network/firewall changes require owner confirmation. Report sent per-server and per-client via email plugin/skill (not bundled). Dependency: SSH MCP server must be running.
version: 1.4.0
metadata: {"openclaw": {"emoji": "๐ก๏ธ", "requires": {"bins": ["bash","python3","ss","iptables","systemctl","grep","awk","sed","find","curl"], "mcp": ["ssh_conn","ssh_exec"]}}}
---
# Linux Security Guardian
## โก SSH MCP โ REQUIRED DEPENDENCY
> **SSH MCP is a hard dependency. The agent MUST have SSH MCP tools available to operate.**
> No local/legacy fallback. All operations go through SSH MCP.
### Prerequisite
```yaml
# SSH MCP server must be running and accessible
# Tools required: ssh_conn, ssh_exec
# Config reference: /save_data/projects/ssh_mcp/
dependency: ssh_mcp
status: required # if unavailable โ ABORT, alert owner
```
### Server Profile Config
Each target server needs a saved connection in SSH MCP database. Configure in `SERVER_PROFILE.md`:
```yaml
ssh_mcp:
connection_id: "<id-name-or-alias-from-ssh-conn-list>" # Saved connection ID, Name, or Alias
# OR inline config:
# host: "<server-ip>"
# port: 22
# username: "<user>"
# key_path: "</path/to/key>"
```
### Connection Lifecycle
```
1. ssh_conn(op="list") โ find target server connection_id
โ If not found โ log error, ABORT audit (no fallback)
2. ssh_exec(op="open", connectionId) โ returns sessionId
โ If fails โ log error, ABORT audit
โ sessionId used for ALL subsequent commands
3. Run commands in audit modules:
โ Prefer passing multiple commands in a module as a sequential array to reduce overhead: `ssh_exec(op="run", sessionId, command=["cmd1", "cmd2", ...])` โ returns a single commandId.
โ Alternatively, run individually: `ssh_exec(op="run", sessionId, command="<command>")`.
โ If multiple command runs are triggered concurrently, the SSH MCP server's self-healing queue handles concurrency. If the target server rejects channel opens (due to low `MaxSessions`), the MCP server dynamically drops the concurrency limit, unshifts the task, and retries with backoff.
โ Retrieve output: `ssh_exec(op="logs", commandId=commandId, stream="stdout")`.
4. ssh_exec(op="close", sessionId) after audit complete
```
### SSH MCP Tool Usage
| Operation | SSH MCP Tool | Notes |
|-----------|-------------|-------|
| List/Manage connections | `ssh_conn(op="list")` | Find target server by name/IP |
| Connect to server | `ssh_exec(op="open", connectionId)` | Returns sessionId |
| Execute command | `ssh_exec(op="run", sessionId, command)` | Returns commandId (non-blocking) |
| Get command output | `ssh_exec(op="logs", commandId)` | Can filter: grep, head, tail, fromLine, toLine |
| Get command status | `ssh_exec(op="status", commandId)` | Check if still running |
| Disconnect | `ssh_exec(op="close", sessionId)` | Always disconnect after audit |
| List active sessions | `ssh_exec(op="list")` | Monitor active connections |
| Bulk execution | `ssh_bulk_exec(commands, connectionIds)` | Run command(s) in bulk across servers |
| Bulk audit checks | `ssh_bulk_audit(op, client)` | Run health/sysinfo/security checks in bulk |
| Client CRUD management | `ssh_client(op="list")` | Manage client groups and servers ownership |
### Audit Modules
All 18 modules execute commands via SSH MCP. Each module file lists commands that get wrapped with `ssh_exec(op="run", sessionId, command)`:
```
module command โ ssh_exec(op="run", sessionId, command="module command")
โ ssh_exec(op="logs", commandId=cmdId)
โ parse output
```
### CVE Scan
The external CVE scan runs locally (on the guardian host) using curl to CISA KEV, OSV.dev, and NVD API.
Usage requires `--client` and `--server` to write results to per-server paths:
```bash
bash cve/cve-scan.sh --client "client-1" --server "server-01"
# Writes results to:
# cve/<client>/<server>/scan-results/YYYY-MM-DD.md
# cve/<client>/<server>/advisories/<CVE-ID>.md
```
Steps:
```bash
# 1. SSH MCP: ssh_exec(op="run", sessionId, command="dpkg-query -W ...") โ save locally
# 2. Read from cve/<client>/<server>/scan-results/installed-packages.txt
# 3. curl CISA KEV โ filter Linux entries โ write advisories
# 4. curl POST OSV.dev batch โ match packages โ write advisories
# 5. curl NVD API (optional) โ cross-check โ write advisories
```
---
## Multi-Client Architecture
The guardian manages **multiple clients**, each with their own server fleet.
SERVER_PROFILE.md defines `## Client:` sections. The audit iterates ALL.
```
SERVER_PROFILE.md
โโโ ## Client: client-1 (7 servers)
โ โโโ server-01
โ โโโ server-02
โ โโโ ... server-07
โโโ ## Client: client-2 (N servers) โ add as needed
โ โโโ ...
โโโ ## Client: [NEXT-CLIENT]
```
All paths use `<client>/<server>/` prefix:
- Findings: `audit/results/<client>/<server>/<severity>/`
- Actions: `actions/<client>/<server>/auto-done/`
- CVEs: `cve/<client>/<server>/advisories/`
- Reports: `reports/<client>/<server>/daily/`
---
## Purpose
Agent manages complete Linux server security autonomously via SSH MCP.
Every night at 1 AM IST:
- Iterates all clients โ all servers
- Full security audit runs via SSH MCP
- CVEs scanned against installed packages
- Auto-fixes applied for safe issues
- Critical issues queued for owner confirmation
- Per-server, per-client, and master email reports delivered
---
## Action Decision Matrix
The most important thing โ what agent does vs what it asks first:
| Finding Type | CVSS / Severity | Action |
|---|---|---|
| CVE โ Critical | โฅ 9.0 | EMAIL ALERT immediately + queue for confirm |
| CVE โ High | 7.0โ8.9 | Queue for confirm + include in report |
| CVE โ Medium | 4.0โ6.9 | Include in report + advisory |
| CVE โ Low | < 4.0 | Info in report only |
| CVE โ KEV (CISA) | any | **Treated as CRITICAL** โ immediate alert + confirm within due date |
| CVE โ KEV + Ransomware | any | **๐ฅ HIGHEST PRIORITY** โ immediate alert, confirm ASAP |
| Kernel update available | any | Confirm required before patch |
| Security-only pkg update | any | Confirm required |
| SSH: PermitRootLogin yes | critical | Alert + confirm to fix |
| SSH: PasswordAuth yes | high | Alert + confirm to fix |
| SSH: Port 22 | medium | Advisory only |
| Empty password account | critical | AUTO-LOCK immediately |
| Unknown root-uid account | critical | Alert + confirm to lock |
| Inactive account > 90d | medium | Alert + confirm to lock |
| World-writable /tmp | medium | AUTO-FIX chmod |
| World-writable system dir | high | Alert + confirm to fix |
| Unexpected SUID binary | high | Alert only (owner decides) |
| Failed login spike > 20/hr | high | Alert immediately |
| New unknown cron job | high | Alert immediately |
| Firewall rule change needed | any | CONFIRM REQUIRED always |
| Open unexpected port | high | Alert + confirm to close |
| Service: unnecessary running | medium | Alert + confirm to stop |
| SSL cert expiring < 30d | warning | Alert |
| SSL cert expired | critical | Alert immediately |
| Disk > 85% full | warning | Alert |
| Disk > 95% full | critical | Alert immediately |
| Auditd not running | high | AUTO-START + alert |
| fail2ban not running | high | AUTO-START + alert |
| Log file suspicious entry | high | Alert with extract |
---
## Audit Modules
| Module | What it checks | SSH MCP Command |
|--------|---------------|-----------------|
| `01-system` | OS, kernel, uptime, last reboot, hardware | `ssh_exec(op="run", sessionId, command="uname -a; cat /etc/*release")` |
| `02-users` | Accounts, root access, sudo, empty passwords, inactive | `ssh_exec(op="run", sessionId, command="cat /etc/passwd; cat /etc/shadow; ...")` |
| `03-ssh` | sshd_config full audit โ 20+ checks | `ssh_exec(op="run", sessionId, command="cat /etc/ssh/sshd_config")` |
| `04-auth` | Login history, failed logins, PAM config | `ssh_exec(op="run", sessionId, command="last; cat /var/log/auth.log")` |
| `05-services` | Running services, unnecessary ones, failed units | `ssh_exec(op="run", sessionId, command="systemctl list-units ...")` |
| `06-packages` | Pending updates, security updates count | `ssh_exec(op="run", sessionId, command="apt list --upgradable 2>/dev/null")` |
| `07-cve` | CVE scan โ remote via SSH MCP + API-based | `ssh_exec(op="run", sessionId, command="dpkg-query -W ...; curl ...")` |
| `08-network` | Open ports, listening services, active connections | `ssh_exec(op="run", sessionId, command="ss -tulpn; netstat -tulpn")` |
| `09-firewall` | iptables/nftables/ufw rules audit | `ssh_exec(op="run", sessionId, command="iptables-save 2>/dev/null")` |
| `10-filesystem` | SUID/SGID, world-writable, /tmp, sticky bits | `ssh_exec(op="run", sessionId, command="find / -perm -4000 ...")` |
| `11-kernel` | sysctl security params โ 15+ checks | `ssh_exec(op="run", sessionId, command="sysctl -a 2>/dev/null")` |
| `12-logs` | auth.log, syslog, kern.log โ anomaly scan | `ssh_exec(op="run", sessionId, command="tail -100 /var/log/syslog")` |
| `13-crons` | System + user cron jobs โ unknown jobs flagged | `ssh_exec(op="run", sessionId, command="cat /etc/crontab; ls -la /var/spool/cron/")` |
| `14-ssl` | Cert expiry check for all domains/services | `ssh_exec(op="run", sessionId, command="openssl x509 -in ... -noout -dates")` |
| `15-docker` | If running โ image vulns, container config | `ssh_exec(op="run", sessionId, command="docker ps; docker images")` |
| `16-disk` | Disk usage, inode usage | `ssh_exec(op="run", sessionId, command="df -h; df -i")` |
| `17-integrity` | AIDE/tripwire check if installed | `ssh_exec(op="run", sessionId, command="aide --check")` |
| `18-rootkit` | rkhunter/chkrootkit if installed | `ssh_exec(op="run", sessionId, command="rkhunter --check --skip-keypress")` |
**Execution rule**: All commands go through `ssh_exec(op="run", sessionId, command="<command>")` โ `ssh_exec(op="logs", commandId=cmdId)`. No local execution.
---
## Finding Severity Levels
| Level | Color | Meaning |
|---|---|---|
| `CRITICAL` | ๐ด | Immediate risk, action required now |
| `HIGH` | ๐ | Significant risk, fix this week |
| `MEDIUM` | ๐ก | Moderate risk, fix this month |
| `LOW` | ๐ต | Minor issue, fix when possible |
| `INFO` | โช | Informational, no action needed |
| `PASS` | ๐ข | Check passed, all good |
---
## Confirmation Flow
When owner confirmation is needed:
```
Finding detected (requires confirm) on <client>/<server>
โ
Write to actions/<client>/<server>/pending-confirm/<client>-<server>-<id>-<slug>.md
โ
Include in email report under "NEEDS YOUR DECISION" with <client>/<server> context
โ
Owner replies with: APPROVE <id> / DENY <id> / SKIP <id>
(Full ID format: <client>-<server>-<type>-<NNN>, e.g. client-1-server-01-ACT-20260529-001)
โ
Search all actions/*/*/pending-confirm/ for the ID
โ
APPROVE โ agent connects to <client>/<server> via SSH MCP โ executes action โ logs to history/
DENY โ action skipped, noted
SKIP โ deferred to next audit
```
---
## Email Report Structure
Reports are sent per-server, per-client (summary), and master. All via email plugin/skill.
### Per-Server Report
```
Subject: [Linux Guardian] <client>/<server> โ YYYY-MM-DD | Score: N/100 | CRITICAL:N HIGH:N
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
LINUX SECURITY GUARDIAN โ NIGHTLY REPORT
Client: <client> | Server: <server> | <IP> | YYYY-MM-DD 01:00 IST
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
EXECUTIVE SUMMARY
Security Score: N/100 | Grade: X
Critical: N | High: N | Medium: N | Low: N
Auto-fixed: N | Pending confirm: N | Passed: N
โโ ๐ด CRITICAL (immediate action needed)
[Finding details]
โโ ๐ HIGH
[Finding details]
โโ โก AUTO-ACTIONS TAKEN (safe, non-breaking)
[What was auto-fixed]
โโ ๐ NEEDS YOUR DECISION (reply APPROVE/DENY/SKIP <id>)
[Pending confirmations with IDs โ includes <client>/<server> prefix]
โโ ๐ฆ CVE REPORT
[CVEs found by severity]
โโ ๐ NETWORK & FIREWALL
[Port/firewall status]
โโ ๐ก MEDIUM / LOW
[Less urgent findings]
โโ ๐ข ALL PASSING
[Checks that passed]
โโ NEXT AUDIT: Tomorrow 01:00 IST
```
### Per-Client Summary Report
```
Subject: [Linux Guardian] <client> Summary โ YYYY-MM-DD | Servers: N/N | CRITICAL:N HIGH:N
Client: <client>
Servers audited: N of N total
Average score: N/100
| Server | Score | Critical | High | Score Grade |
|--------|-------|----------|------|-------------|
| ... | ... | ... | ... | ... |
Cross-server patterns: [same vuln found on multiple servers]
```
---
## Security Score Formula
```
score = 100
score -= (critical_count ร 20)
score -= (high_count ร 10)
score -= (medium_count ร 3)
score -= (low_count ร 1)
score = max(0, score)
Grade: 90-100 = A | 75-89 = B | 60-74 = C | < 60 = F
```
---
## Folder Structure
```
linux-security-guardian/
audit/
modules/ โ 01-system.md ... 18-rootkit.md
results/
<client>/<server>/
critical/ high/ warning/ info/ pass/
YYYY-MM-DD-<check>.md โ per-client/per-server findings
actions/
<client>/<server>/
auto-done/ โ auto-fixed actions (logged)
YYYY-MM-DD-<slug>.md
pending-confirm/ โ waiting for owner
<id>-<slug>.md
history/ โ all approved/denied actions
cve/
cve-scan.sh โ external CVE scanner (takes --client --server)
external-sources.md โ all API URLs, query params, working examples
.cache/ โ shared cached API responses (6h TTL)
<client>/<server>/
scan-results/ โ YYYY-MM-DD.md
advisories/ โ <cve-id>.md
reports/
<client>/<server>/
daily/YYYY-MM-DD.md
weekly/YYYY-WNN.md
network/
<client>/<server>/
firewall-snapshots/ โ YYYY-MM-DD-rules.txt
port-scans/ โ YYYY-MM-DD.md
proposed-changes/ โ <id>-<change>.md
hooks/
audit-runner.md โ main 1 AM audit orchestrator (multi-client loop)
on-critical.md โ fires on any critical finding (with client/server)
on-confirm-reply.md โ processes owner APPROVE/DENY/SKIP
pre-action.md โ safety check before any action
post-action.md โ verify action succeeded
mail-sender.md โ uses email plugin/skill to send report
crons/
active/
nightly-audit.md โ 1 AM IST permanent
completed/
errors/
raw/ โ raw error logs
memory/
schema.json
index.json
SOUL.md โ soul context (multi-client aware)
AGENT.md โ behavioral rules (multi-client, SSH MCP hard dep)
SERVER_PROFILE.md โ multi-client server details
AUDIT_LOG.md โ append-only master log
BASELINE.md โ expected state snapshot
STATS.md
```
don't have the plugin yet? install it then click "run inline in claude" again.