I Woke Up to 150+ Deleted GitHub Repos and a Ransom Note — This Is What Happened
A real developer. A real attack. A real recovery.
I almost didn't write this.
Partly because it's embarrassing. Partly because I'm still angry about it. But mostly because I know there are developers out there running the exact same tools I was running, making the exact same mistakes I was making — and I don't want them to wake up to what I woke up to on the morning of March 24, 2026.
So here it is. The full story. No sugar coating.
The Morning Everything Was Gone
I opened my laptop like any other morning. Grabbed my coffee, opened GitHub, and just… froze.
My repositories were gone.
Not some of them. Not a few. Over 150 repositories across multiple organizations — personal projects, client work, production backends — all gone. Replaced by repositories with random UUID names, each containing a single file with this message:
All production database backups have been deleted from your systems
and securely stored in our databases.
Contact for Backup: https://t.me/cyberluffy
My stomach dropped.
I checked my GitHub audit log. The damage was methodical and deliberate. Someone had:
- Removed all my repos from every integration — SonarCloud, Vercel, AWS Amplify, AWS Connector for GitHub, Cursor — all of it
- Then deleted the repositories themselves
- The activity was traced to IP 188.241.177.181 — São Paulo, Brazil
I had never been to Brazil.
My First Reaction (And What You Should Do First)
I panicked. I won't lie. But I forced myself to slow down and think.
The first thing I did was change my GitHub password and start revoking tokens. But here's what I didn't fully understand yet — changing your password means nothing if the attacker is using a token. Tokens are independent of your password. I had to revoke everything.
If this is happening to you right now, do this immediately:
- Go to GitHub → Settings → Developer Settings → Personal Access Tokens → Revoke ALL
- Settings → SSH and GPG Keys → Delete ALL
- Settings → Applications → Remove anything suspicious
- Settings → Security → Sessions → Sign out all other sessions
- Enable 2FA if you haven't already — use an authenticator app, not SMS
- Go to support.github.com and open an emergency ticket — time matters for repo restoration
I opened a GitHub support ticket within the first hour. That was one of the best decisions I made that day.
How Did They Even Get In?
This is the part that took me a while to figure out. And honestly, the answer surprised me.
They didn't brute force my password. They didn't phish me. They didn't exploit some obscure vulnerability.
I let them in myself. Without knowing it.
A few weeks earlier I had come across an AI agent tool called OpenClaw. It was marketed as a developer productivity tool — an AI gateway that could help automate workflows. I installed it, tried it out briefly, and kind of forgot about it.
npm install -g openclaw
That one command changed everything.
What I didn't know was that OpenClaw installed a persistent background service on my Mac — a gateway that ran 24/7, survived reboots, and had full access to my filesystem. I found it hiding in my LaunchAgents:
~/Library/LaunchAgents/ai.openclaw.gateway.plist
Opening that file made my blood run cold:
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/node</string>
<string>/opt/homebrew/lib/node_modules/openclaw/dist/index.js</string>
<string>gateway</string>
<string>--port</string>
<string>18789</string>
</array>
RunAtLoad: true. KeepAlive: true. It was designed to always be running. Always listening. On port 18789.
The gateway logs told the rest of the story. This thing had been running since March 17 — a full 7 days before I noticed anything. And it wasn't just sitting there. It was connected to my WhatsApp. It was advertising itself on my local network. It had access to everything on my machine.
But the real damage came from something embarrassingly simple.
The $0 Mistake That Actually Caused This
While digging through my shell history, I found this:
git remote set-url origin https://drbenzene:ghp_WT********oIYa57uNoVz3kkDKWXMGgOAW5N0xhm5u@github.com/company/backend_code.git
There it was. My GitHub Personal Access Token. Sitting in plain text in my bash history.
I had done what so many developers do — embedded a token directly in a git remote URL to avoid being prompted for credentials. It's quick. It's convenient. And it is catastrophically dangerous.
That token had full repository access. OpenClaw read my shell history, extracted the token, and handed it to whoever was on the other end.
The full attack chain was:
I install OpenClaw to try it out
↓
OpenClaw runs silently for 7 days with full filesystem access
↓
Reads ~/.bash_history and ~/.zsh_history
↓
Finds GitHub PAT stored in plain text in remote URL
↓
Attacker uses token to access GitHub API
↓
Removes repos from all integrations
↓
Deletes all 150+ repositories
↓
Creates ransom note repos
↓
I wake up to a nightmare
Seven days. One npm install. One bad habit with git tokens.
The Investigation — What I Checked and How
I want to be thorough here because this is the part most blog posts skip. Here's exactly what I checked to understand the full scope of the breach.
Checking My Mac
LaunchAgents and LaunchDaemons — where malware hides on Mac:
ls ~/Library/LaunchAgents/
ls /Library/LaunchAgents/
ls /Library/LaunchDaemons/
This is where I found OpenClaw.
Active network connections:
lsof -i | grep ESTABLISHED
Running processes:
ps aux
Cron jobs:
crontab -l
sudo crontab -l
Shell history for exposed secrets:
cat ~/.zsh_history | grep -E "ghp_|token|password|secret|key"
This is where I found a second exposed token — for another GitHub organization. I revoked it immediately.
Login history:
last
Good news here — no remote logins to my Mac. The attacker never directly SSH'd into my machine. They operated entirely through the OpenClaw gateway.
Checking My Production Servers
I SSH'd into my live backend server and ran:
# Who has logged in?
last -n 50
# Any unauthorized users?
cat /etc/passwd | grep -v nologin | grep -v false
# Recently modified files?
find /etc -mtime -7 -type f 2>/dev/null
# What's in authorized_keys?
cat ~/.ssh/authorized_keys
The server was clean — no unauthorized logins, no backdoor users, no modified files. But my server's bash history also had an exposed token in it. I revoked that too.
The Cleanup — Exactly What I Did
1. Killed the Backdoor
# Stop OpenClaw immediately
launchctl unload ~/Library/LaunchAgents/ai.openclaw.gateway.plist
# Delete the LaunchAgent
rm ~/Library/LaunchAgents/ai.openclaw.gateway.plist
# Uninstall the package
npm uninstall -g openclaw
# Remove all its data
rm -rf ~/.openclaw
2. Deleted All Old SSH Keys
# Remove all old keys from my Mac
rm ~/.ssh/id_rsa ~/.ssh/id_rsa.pub
rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
rm ~/.ssh/company_key
rm ~/.ssh/prodevs_key ~/.ssh/prodevs_key.pub
rm ~/.ssh/azure_new_key ~/.ssh/azure_new_key.pub
rm ~/.ssh/your_key_name ~/.ssh/your_key_name.pub
Also removed the old key from my production server:
# On the server - remove the old compromised key
sed -i '/generated-by-azure/d' ~/.ssh/authorized_keys
3. Generated Fresh SSH Keys
# Dedicated key for GitHub
ssh-keygen -t ed25519 -C "my@email.com" -f ~/.ssh/github_key
# One key for all servers
ssh-keygen -t ed25519 -C "my@email.com" -f ~/.ssh/servers_key
Why two separate keys? If one gets compromised, the other is still safe. At minimum, keep your GitHub key separate from your server keys.
4. Set Up SSH Config Properly
nano ~/.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
Host Company-Live
HostName YOUR_SERVER_IP
User azureuser
IdentityFile ~/.ssh/servers_key
5. Switched All Repos From HTTPS to SSH
# Never again will I use this format
# git remote set-url origin https://user:TOKEN@github.com/org/repo.git
# This is the right way
git remote set-url origin git@github.com:username/repo.git
6. Cleared My Shell History
cat /dev/null > ~/.bash_history
cat /dev/null > ~/.zsh_history
history -c
7. Ran Security Scans
I downloaded KnockKnock from Objective-See (objective-see.org) — it scans every persistence mechanism on your Mac. All 17 items it found were legitimate. Clean.
I also ran Malwarebytes for Mac. Clean.
What the Security Scans Showed
KnockKnock scanned every category:
- Launch Items: 17 found — all legitimate (Docker, MySQL, Nginx, Redis, etc.)
- Login Items: 3 found — all legitimate (Electron app, PDFgear, Docker)
- Kernel Extensions: 0
- Library Inserts: 0
- Library Proxies: 0
- Login/Logout Hooks: 0
No traces of OpenClaw remained. The cleanup was complete.
About the Ransom — Don't Pay It
The ransom note claimed they had "securely stored backups" of all my deleted repositories. Let me be very direct: this is almost certainly a lie.
GitHub repository deletion is immediate and irreversible from the attacker's side. They deleted my repos and left a note — they almost certainly do not have my code.
Do not contact them. Do not pay. Instead:
- Contact GitHub support immediately — they may be able to restore recently deleted repos
- Check if any collaborators have local clones
- Check Vercel, AWS Amplify, Netlify — they often cache your code
- Check your own local machine for cloned copies
The Lessons I'm Taking Forward
Never Embed Tokens in Git URLs
# ❌ This stores your token in shell history forever
git remote set-url origin https://username:ghp_TOKEN@github.com/org/repo.git
# ✅ Use SSH — clean, secure, no tokens exposed
git remote set-url origin git@github.com:org/repo.git
Vet Every Tool You Install — Especially AI Agents
I installed OpenClaw because it looked interesting and useful. I didn't check:
- Who published the npm package
- What permissions it was requesting
- Why it needed to run as a persistent background service
- Whether it was open source and auditable
AI agent tools are a new category of developer tool that often requires deep system access — filesystem, network, environment variables. That power can be abused.
Before installing any tool like this:
# Check who published it and when
npm info PACKAGE_NAME
# Look at the package contents before installing
npx --yes npm-package-inspect PACKAGE_NAME
Audit Your LaunchAgents Regularly
# Run this monthly
ls ~/Library/LaunchAgents/
ls /Library/LaunchAgents/
ls /Library/LaunchDaemons/
Download KnockKnock and run it monthly. It takes 2 minutes and could save you everything.
Use Separate SSH Keys for Separate Purposes
~/.ssh/github_key → GitHub only
~/.ssh/servers_key → All production servers
If you manage multiple GitHub accounts:
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/github_personal_key
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work_key
Enable 2FA — But Not SMS
SMS 2FA can be SIM-swapped. Use an authenticator app:
- Google Authenticator
- Authy
- 1Password (built-in TOTP)
Never Store Secrets in Shell History
Add this to your .zshrc or .bashrc:
# Prevent specific commands from being saved to history
export HISTIGNORE="*TOKEN*:*token*:*password*:*secret*:*ghp_*"
# Or increase history size but add timestamps for auditing
export HISTTIMEFORMAT="%F %T "
Better yet — use a secrets manager like 1Password or Bitwarden and never type tokens directly into the terminal.
The Developer Security Checklist I Now Follow
I built this after the incident. Review it monthly:
GitHub:
[ ] 2FA enabled with authenticator app (not SMS)
[ ] No tokens embedded in git remote URLs
[ ] SSH used instead of HTTPS for all repos
[ ] Audit log checked for suspicious activity
[ ] Old/unused tokens revoked
[ ] SSH keys rotated every 6 months
Mac:
[ ] LaunchAgents audited monthly
[ ] KnockKnock scan run monthly
[ ] Malwarebytes scan run monthly
[ ] All new tools vetted before installation
Servers:
[ ] authorized_keys reviewed regularly
[ ] Login history checked
[ ] No unknown user accounts
[ ] .env secrets rotated after any compromise
General:
[ ] Secrets manager in use (1Password, Bitwarden)
[ ] No plaintext tokens anywhere in shell history
[ ] .env in global .gitignore
[ ] 2FA on every critical service
Where Things Stand Now
GitHub support is working on repo restoration. My Mac is confirmed clean by both KnockKnock and Malwarebytes. All credentials have been rotated. SSH is set up properly. My production server is secure.
It was a brutal day. Honestly one of the worst days I've had as a developer. But looking back, every single thing that went wrong was preventable. And that's exactly why I wrote this.
The attack wasn't sophisticated in some magical, unstoppable way. It worked because:
- I installed a tool without fully vetting it
- I had a bad habit of embedding tokens in git URLs
- I didn't regularly audit what was running on my machine
All fixable. All preventable. Starting today.
One Last Thing
If you're reading this and you have tokens embedded in git remote URLs right now — please go fix them. Right now. Before you finish reading this.
# Find all repos using HTTPS with tokens
grep -r "https://.*:.*@github.com" ~/.gitconfig
grep -r "https://.*:.*@github.com" ~/*/. git/config 2>/dev/null
# Fix them
git remote set-url origin git@github.com:username/repo.git
It takes 30 seconds. It could save you everything.
If this helped you or if you've had a similar experience, I'd love to hear about it in the comments. Let's help each other stay safe out there.
And if you found this useful — share it. Another developer somewhere needs to read this today.
Let's Connect
Tags: security github developer ssh hacking incidentresponse nodejs devops macsecurity career
Top comments (0)