| name | machine-security-check |
| description | This skill should be used when the user asks to "check machine security", "run a security audit", "is my mac secure", "scan my machine", "audit my mac", or mentions SIP, Gatekeeper, FileVault, firewall, login items, launch agents, SSH keys, or authorized_keys. Performs a read-only macOS security posture audit and writes a structured JSON result to ~/.mac-guardian/data/. |
machine-security-check
Performs a read-only posture audit of a macOS machine across system protections, persistence points, and credential surfaces, then writes the result to the shared data directory.
When to invoke
Trigger on phrases like: "check machine security", "security audit", "is my mac secure", "scan my machine", "audit my mac".
What to check
Run each check as a read-only shell command. Never prompt for or request sudo. If a command needs elevation and is not available without it, record the check with severity info and a detail of "not available without elevation" rather than requesting privileges.
System protections (severity guidance in parens)
- SIP —
csrutil status. Expect "enabled". If disabled, severity critical.
- Gatekeeper —
spctl --status. Expect "assessments enabled". If disabled, warn.
- FileVault —
fdesetup status. Expect "On". If "Off", critical. If not determinable, info.
- Application Firewall —
defaults read /Library/Preferences/com.apple.alf globalstate 2>/dev/null. 0 = off (warn), 1 or 2 = on (ok).
- Automatic Software Updates —
defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null and related keys. Off is info.
- Screen-lock —
defaults read com.apple.screensaver askForPassword 2>/dev/null. Unset or 0 is warn.
Persistence and startup
- Login items —
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null. List names; if any look unfamiliar, mark individual findings info.
- User LaunchAgents —
ls -la ~/Library/LaunchAgents 2>/dev/null. Report count and any with very recent mtime (<7 days) as info. Any unsigned binary target = warn.
- System LaunchAgents / Daemons —
ls /Library/LaunchAgents /Library/LaunchDaemons 2>/dev/null. Report counts only (avoid flooding findings).
- Cron / at —
crontab -l 2>/dev/null and atq 2>/dev/null. Any entries = info with the content in raw.
Credential surfaces
- SSH keys — enumerate
~/.ssh/id_* (not .pub). For each, report type and whether it is encrypted (grep -q "ENCRYPTED" <key> or ssh-keygen -y -P "" -f <key> >/dev/null 2>&1). Unencrypted private keys = warn.
- authorized_keys —
~/.ssh/authorized_keys. Report line count. >0 entries = info with the comment fields (last field) listed.
- Keychain —
security list-keychains. Just report names as raw, no severity.
Recent filesystem activity
- Modifications in sensitive dirs in last 7 days —
find /Library/LaunchAgents /Library/LaunchDaemons ~/Library/LaunchAgents ~/.ssh -type f -mtime -7 2>/dev/null. Any result = info, list up to 20 paths.
- Shell rc suspicious patterns — grep
~/.zshrc ~/.bashrc ~/.bash_profile ~/.profile for curl | sh, wget | sh, eval \"\$(curl, or base64-decoded eval. Matches = warn.
Output contract
After collection, construct a single JSON envelope matching the shared schema:
{
"skill": "machine-security-check",
"timestamp": "<ISO8601 UTC>",
"severity": "<highest finding severity: ok|info|warn|critical>",
"summary": "<one-line human summary, e.g. 'All protections on. 2 informational items.'>",
"findings": [
{ "id": "sip", "severity": "ok", "title": "SIP enabled", "detail": "System Integrity Protection: enabled." }
],
"raw": { "<key>": "<trimmed raw output>" }
}
Write it to ~/.mac-guardian/data/machine-security-check-<ISOdate>.json. Use the helpers in ${CLAUDE_PLUGIN_ROOT}/scripts/_common.sh when scripting; or write directly using date +%Y-%m-%d for the filename.
Handoff
After writing JSON:
- If invoked directly by the user (not by
daily-health-report), also render and open a standalone mini HTML report:
bash ${CLAUDE_PLUGIN_ROOT}/scripts/render-single.sh machine-security-check
- If invoked by
daily-health-report, return the JSON path only.
Safety
- Read-only. Never modify files. Never toggle SIP, FileVault, or firewall.
- Do not request
sudo. If elevation would be required for a check, record it as informational.
- Never print private key contents — only report their existence and encryption state.