Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
14bfdca
Add PRD: Autonomous Security Improvement Loop
Mar 19, 2026
8f34bb2
Merge remote-tracking branch 'origin/main' into kyle/prd-security-imp…
Mar 19, 2026
0b217dc
Add design doc: Autonomous Security Improvement Loop
Mar 19, 2026
0017006
design-doc: incorporate researcher findings (CLI flags, lock file pat…
Mar 19, 2026
19cf653
design-doc: approve Autonomous Security Improvement Loop
Mar 19, 2026
0823adb
implement: Autonomous Security Improvement Loop
Mar 19, 2026
cae0fe1
refactor: split discord into status/log channels, restore on agent fa…
Mar 19, 2026
a57a82e
add --no-session-persistence, document implementation divergences
Mar 19, 2026
cff2784
docs: add README for security improvement loop
Mar 19, 2026
9a37ed9
add --dangerously-skip-permissions to claude invocations
Mar 19, 2026
c7698ae
consolidate output to single log file at /tmp/sec-loop.log
Mar 19, 2026
089008f
add inner retry loop: improve→verify up to 3 attempts per finding
Mar 19, 2026
6ca245f
log attempt progress to discord, soften verifier on final attempt
Mar 19, 2026
e86e473
add shared run-notes.md between improvement and adversarial agents
Mar 19, 2026
df1c274
prefix discord messages with sec-loop:, add iteration start announcement
Mar 19, 2026
a86ff32
sec-loop: protect exports.sh and secrets/ in sensitive file hook
Mar 19, 2026
ad6adcb
sec-loop: source exports.sh so Discord notifications actually work
Mar 19, 2026
c162cf5
sec-loop: raise daily budget from $150 to $200
Mar 19, 2026
59a8e9d
sec-loop: raise max verify retries from 3 to 5
Mar 19, 2026
7325af0
sec-loop: reduce sleep interval from 30min to 20min
Mar 19, 2026
8be8971
sec-loop: broaden scope from hooks-only to full Mac workstation security
Mar 19, 2026
c309fc6
sec-loop: add --one-shot flag to exit after one iteration
Mar 19, 2026
444b0e2
sec-loop: give agents Discord MCP access via minimal runtime config
Mar 19, 2026
93134f4
sec-loop: restructure Discord output — narrative status, detailed logs
Mar 19, 2026
b00afd4
sec-loop: reduce sleep interval to 15min
Mar 19, 2026
d722831
sec-loop: hardcode Discord channel ID in prompt instead of env var
Mar 19, 2026
302a73c
sec-loop: push to origin after each verified commit
Mar 19, 2026
a6eb15e
sec-loop: deploy Grep|Glob matcher fix and rewrite protect-sensitive.sh
Mar 19, 2026
24f44fc
sec-loop: escalating pivot pressure on repeated verification failures
Mar 19, 2026
ece1f3b
sec-loop: fix — fnmatch args reversed in check_glob_filter: fnmatch(u…
Mar 19, 2026
04b80c6
sec-loop: reduce sleep interval to 10min
Mar 19, 2026
3097c0f
sec-loop: forbid SSH and Tailscale SSH config changes
Mar 19, 2026
f16686a
sec-loop: fix — macOS Application Firewall was disabled (State = 0). …
Mar 19, 2026
3e2dd18
sec-loop: fix — /etc/sudoers.d/claude-temp granted unrestricted passw…
Mar 19, 2026
9c5b6d4
sec-loop: fix — audit-log.sh logged Grep/Glob calls with empty param
Mar 19, 2026
9c91636
sec-loop: fix — audit-log.sh Grep/Glob logging was fixed in source (i…
Mar 19, 2026
3c09631
sec-loop: fix — shell quoting fragments grep checks for sensitive pat…
Mar 19, 2026
e785b23
sec-loop: enforce diversity across iterations, no repeating areas
Mar 19, 2026
fe81faf
sec-loop: add operator steering log to run-notes
Mar 19, 2026
4e4d6fb
playbook: always assign PRs to kylep in system CLAUDE.md
Mar 19, 2026
3dea26b
sec-loop: mark audit-log.sh as off-limits
Mar 19, 2026
cc28fb7
sec-loop: mark MCP config files as off-limits
Mar 19, 2026
0de0af7
sec-loop: mark chmod/file permission fixes as off-limits
Mar 19, 2026
fb8ddf8
sec-loop: stronger MCP off-limits rule, revert loop's MCP changes
Mar 19, 2026
59733bc
sec-loop: fix cost gate crash on malformed token count
Mar 20, 2026
3a6a7ec
sec-loop: rewrite from bash to Python with 35 unit tests
Mar 20, 2026
42a7f06
sec-loop: overhaul prompts for efficiency based on log analysis
Mar 20, 2026
52bd249
sec-loop: reduce verifier max turns to 12
Mar 20, 2026
74f10f2
sec-loop: poll #status-updates for operator directives each iteration
Mar 20, 2026
4430b93
sec-loop: remove loop.sh, replaced by loop.py
Mar 20, 2026
254efcb
sec-loop: add User-Agent header to Discord API calls
Mar 20, 2026
21192f3
sec-loop: differentiate operator directives by Discord author
Mar 20, 2026
6599ae3
sec-loop: add operator-directives.md (generated by loop)
Mar 20, 2026
a3cca44
sec-loop: log phases to Discord #log channel more eagerly
Mar 20, 2026
b75e800
sec-loop: fix — Ansible playbook set logs/ directory to mode 0755, wh…
Mar 20, 2026
8ab08bc
sec-loop: add per-phase log files and 10min timeout
Mar 20, 2026
aba4e72
sec-loop: fix — macOS screen lock completely unconfigured — no idle t…
Mar 20, 2026
3b116d2
sec-loop: fix — FileVault is Off — disk unencrypted, physical access …
Mar 20, 2026
7d3c0d2
sec-loop: fix lock file disappearing — only owning PID can delete
Mar 20, 2026
d466c8c
sec-loop: fix — Git security settings (protectHFS, protectNTFS, fetch…
Mar 20, 2026
ec82816
sec-loop: fix — Gatekeeper (spctl --master-enable) enabled live but m…
Mar 21, 2026
1aa7d9a
sec-loop: fix — AirDrop enabled (DisableAirDrop NOT SET) — nearby-dev…
Mar 21, 2026
d452a07
sec-loop: fix — AutomaticallyInstallMacOSUpdates missing from playboo…
Mar 21, 2026
6c104cf
sec-loop: fix — AutomaticallyInstallMacOSUpdates missing from playboo…
Mar 21, 2026
8b390e4
sec-loop: fix — HOMEBREW_VERIFY_ATTESTATIONS=1 set live in ~/.zprofil…
Mar 21, 2026
4ec7c72
sec-loop: revert — protectHFS, protectNTFS, fetch.fsckObjects, transf…
Mar 22, 2026
7a6bf26
sec: remove protect-sensitive hook — fundamentally incompatible with …
Mar 22, 2026
0150fda
sec-loop: fix — playbook was failing due to missing sudo and FileVaul…
Mar 22, 2026
3698c11
logs: add security-loop-summary.md — condensed human-readable chronicle
Mar 22, 2026
0c77c3b
sec: add git object integrity and path traversal hardening to playbook
Mar 22, 2026
eb3c8d4
rca: security loop lower impact than expected
Mar 22, 2026
dd65d8e
sec: action Lynis findings — install rkhunter, harden sshd_config + uucp
Mar 22, 2026
de4c7f1
sec: add NIST mSCP (macos_security) as macOS-native CIS Level 1 auditor
Mar 22, 2026
9361518
sec: add daily security scan LaunchDaemon (lynis + rkhunter + mSCP at…
Mar 22, 2026
2a09853
sec: run security scan immediately on first deploy
Mar 22, 2026
781090a
sec: make scan block and always run (not just on first deploy)
Mar 22, 2026
295217b
sec: make scan log dir world-readable so pai user can read logs
Mar 22, 2026
9d2f6ca
sec: raise scan timeout to 20min (rkhunter takes longer than 5min)
Mar 22, 2026
e53b137
sec: configure rkhunter whitelists and improve scan debugging
Mar 22, 2026
0702d66
sec: fix Lynis ownership check when run as root
Mar 22, 2026
6d0cc7e
sec: run Lynis as brew user to avoid ownership check
Mar 22, 2026
c033eca
sec: fix all scanner issues and extract machine vars to config file
Mar 22, 2026
d27ea06
sec: batch 2-5 CIS Level 1 hardening tasks in security-scan-setup.yml
Mar 23, 2026
adda63b
sec: reach 80/93 CIS L1 checks by fixing pref write locations
Mar 23, 2026
eaa5f15
sec: configure mSCP exemptions for MDM-only checks; show 0 real failures
Mar 23, 2026
ac68433
blog: add Ralph: Secure My Laptop post with generated image
Mar 23, 2026
251bf6a
chore: allow CodeRabbit to review bot-opened PRs
Mar 23, 2026
083d037
Merge branch 'main' into kyle/prd-security-improvement-loop
kylep Mar 23, 2026
e00c4f4
Fix unreachable header logic and escaped pipes in design doc
kylep Mar 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/scheduled_tasks.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"sessionId":"c769c626-6c26-4d94-8468-6497f5b6e783","pid":64517,"acquiredAt":1774058055661}
1 change: 1 addition & 0 deletions .claude/worktrees/focused-hugle
Submodule focused-hugle added at 27aa2e
1 change: 1 addition & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ reviews:
high_level_summary: true
auto_review:
enabled: true
ignore_bots: false
base_branches:
- main

Expand Down
107 changes: 107 additions & 0 deletions apps/agent-loops/macbook-security-loop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Autonomous Security Improvement Loop

Long-running Python script that spawns Claude Code every 10 minutes to
iteratively discover and fix security gaps on the Mac workstation,
with adversarial verification and cost controls.

Originally written in bash (`loop.sh`), rewritten in Python after the
script outgrew bash — JSON parsing, JWT generation, integer arithmetic
on token counts, and Discord API calls were all fighting bash's type
system. The final straw was a cost gate crash caused by bash arithmetic
choking on a multi-line string that Python would have handled as a
simple `int()` call.

Design doc: `apps/blog/blog/markdown/wiki/design-docs/security-improvement-loop.md`

## Usage

```bash
cd ~/gh/multi
python3 apps/agent-loops/macbook-security-loop/loop.py
```

One iteration without commits or Discord:

```bash
python3 apps/agent-loops/macbook-security-loop/loop.py --dry-run
```

One full iteration (commits + push) then exit:

```bash
python3 apps/agent-loops/macbook-security-loop/loop.py --one-shot
```

Follow the log:

```bash
tail -f /tmp/sec-loop.log
```

### Long-running (tmux)

```bash
tmux new -s sec-loop
cd ~/gh/multi
python3 apps/agent-loops/macbook-security-loop/loop.py
# Ctrl-b d to detach
```

## Tests

```bash
cd apps/agent-loops/macbook-security-loop
python3 -m pytest test_loop.py -v
```

## Required env vars

All parsed from `apps/blog/exports.sh` (no need to source it first):

| Variable | Purpose |
|----------|---------|
| `DISCORD_BOT_TOKEN` | Discord bot authentication |
| `DISCORD_STATUS_CHANNEL_ID` | Milestones (iteration complete, termination, budget) |
| `DISCORD_LOG_CHANNEL_ID` | Operational logs (failures, warnings) |
| `GITHUB_APP_ID` | GitHub App for git push |
| `GITHUB_APP_PRIVATE_KEY_B64` | Base64-encoded PEM key |
| `GITHUB_INSTALL_ID` | GitHub App installation ID |

Discord and push are optional — the script no-ops if credentials are unset.

## How it works

Each iteration:

1. **Cost gate** — sums today's token usage from `~/.claude/projects/` JSONL
logs. Stops if over $200/day.
2. **Improvement** — `claude -p prompt.md` finds and fixes one security gap
($5 cap, 30 turns).
3. **Verification** — `claude -p verify-prompt.md` adversarially tests the
fix ($2 cap, 15 turns).
4. **Commit or revert** — passes get committed and pushed, failures get
`git restore`'d.
5. **Sleep 10 minutes**, repeat.

The loop self-terminates when the improvement agent reports no gaps remain.

Retries escalate: attempt 2 asks for a different approach, attempt 3
suggests abandoning, attempt 4+ strongly recommends pivoting to a
different area entirely.

## Steering the loop

The operator can steer the loop remotely by editing `prompt.md`,
`verify-prompt.md`, or `run-notes.md` — these are re-read fresh each
iteration. No restart needed. See "Operator Steering Log" in
`run-notes.md` for the full history.

## Files

| File | Purpose |
|------|---------|
| `loop.py` | Main loop (Python) |
| `test_loop.py` | Unit tests (pytest) |
| `prompt.md` | Improvement iteration prompt for Claude Code |
| `verify-prompt.md` | Adversarial verification prompt for Claude Code |
| `run-notes.md` | Shared scratchpad between agents and operator |
Loading