Skip to content

v0.2.0 — the hour after a breach

Choose a tag to compare

@DareDev256 DareDev256 released this 29 Jul 03:04
· 3 commits to main since this release
v0.2.0
ed9c9b4

The kit was born from a breach and, until now, had nothing for the hour after one. Repo-wide grep before this release: "revoke" 0 hits, "forwarding rule" 0, "deploy key" 0, "reinstall" 0.

If you are in an incident right now

./panic.sh --short     # the ordered checklist, phone-sized, no network needed
./panic.sh --triage    # ...plus live "did anything get root?" probes
./preserve.sh          # capture evidence BEFORE you start cleaning up

Or open INCIDENT.md on your phone.

The ordering is the deliverable. Two steps are commonly inverted, and both inversions waste the whole effort:

  1. Crypto first. It is the only irreversible loss. A seed phrase is the wallet — "change the password" does nothing.
  2. Kill sessions before changing passwords. A stolen cookie authenticates without your password and without your 2FA, and a password change does not reliably invalidate sessions that are already live. Reset first and stop there, and the attacker is still signed in — behind a new password that now protects nothing.

Then: revoke OAuth grants (they survive every password change) → passwords, email first → the mail-persistence sweep (forwarding, filters matching reset/verify/code, send-as aliases, delegated access, app-specific passwords, recovery address and phone — all invisible in normal use, all surviving a reset) → developer tokens in blast-radius order, npm/PyPI publish tokens first, because that is where a personal breach becomes a supply-chain breach.

New in ExposureScan

scan_dev_credentials — the highest-pivot files on a solo dev's Mac, previously unscanned. SSH keys (plaintext vs encrypted, read from the header only), 11 credential files by key name and mode, shell-history token counts by line number, per-profile cookie counts, crypto wallet stores (20 extensions + 13 desktop bundles, unconditional P0), and Firefox login counts so the report is not silently Chrome-shaped.

--tcc — the grant inventory the README's central argument always implied and never delivered. It has always said malware inherits the grants of the trusted binary it runs inside; now it tells you which binaries those are. P0 for terminals, shells, SSH wrappers and bare interpreters holding Full Disk Access, Accessibility or Screen Recording — those are grant-inheritance vehicles, not apps. Run it. The answer is usually uncomfortable.

Fixed: WatchPost could be blinded by one rm

Deleting baseline.json was treated as a first run — the next run printed "No diffing on first run" and silently absorbed whatever had just been planted as legitimate. An .armed marker now makes deletion an alertable event. Editing the baseline directly, to pre-seed an entry so a later plant diffs as already-known, is caught by an HMAC tag. The baseline is 0600 in a 0700 directory; it was 0644, and it enumerates every persistence entry on the machine.

What was deliberately not built

  • preserve.sh defers entirely to Jamf Aftermath when installed. Free, Swift, purpose-built, collects a superset. Reimplementing it would be worse code doing a solved job.
  • No general hardening scanner. FileVault, firewall, update settings, sudoers, the CIS sweep — mSCP and Pareto Security own that and own it better. Only the narrow ClickFix-relevant slice ships.

Honest limits

  • WatchPost's HMAC key sits beside the baseline under the same user, so anyone already running as you can forge it. This is tamper-evidence, not tamper-proofing. The root-owned variant that would be proof is named and not claimed.
  • Safari login counts need a keychain prompt to obtain. The report names the surface and says why, rather than printing a number it cannot stand behind.
  • The Verified badge on this tag only means GitHub matched the signature to a key on this account. git verify-tag against the published fingerprint is the real check, because you control the allowed-signers file and GitHub does not.

Verifying

git verify-tag v0.2.0   # key: SHA256:ahS0yuup97TRBRmaRzk3iEbUlo/IK+VqXgd0sada2KU
./install.sh --verify

Tests

78/78 detection corpus · 10/10 WatchPost baseline integrity · 4/4 pty integration · 72 ExposureScan (was 47). Six CI jobs, four of them on macOS runners. Both feature commits are independently green, so git bisect stays usable.