What to do after running malware from a stranger's repo
Guides · If it already ran · Published 20 October 2026
If you opened, installed or ran a stranger's repo and think it was malicious, treat the machine as compromised. Take it off the network now and stop typing passwords into it. Then, from a different device, revoke and replace everything that machine could reach (GitHub, npm, cloud keys, SSH keys, browser sessions, AI API keys, crypto wallets), look for anything set to start again, and plan a full reinstall. Report the repo and the person who sent it last.
This is for the developer who ran the fake job interview take-home or the client repo that needed a quick fix. Work down the page in order; each step says where the button is and links to the vendor's own instructions. If nothing has run yet, you want how to check a GitHub repo for malware before you clone it instead.
First: contain it
Microsoft's advice for this campaign starts with “isolate the device” (Microsoft, 11 March 2026), and Trend Micro's with “Isolate the machine, revoke credentials” (Trend Micro, 21 April 2026). In practice:
- Disconnect it. Turn off Wi-Fi and unplug any network cable. Leave it switched on if it's a work machine; your security team may want it as it is.
- Stop using it for anything secret. Don't sign in to anything, unlock your password manager, connect a hardware wallet, or plug in a drive you'll use elsewhere.
- If it's a work machine, call your security team now, before the steps below. They may need to rotate company credentials and look at the machine themselves.
- Write down what happened. The repo URL, what you did with it (opened the folder, ran npm install, ran npm start, let an agent in), and roughly when. You'll use the time to read security logs, and the URL to report it.
- Keep the evidence. Screenshot the recruiter or client profile and your messages before you report them, so you still have them if the profile disappears.
Everything in the next section happens on a clean device: your phone, or a computer that never had the repo on it.
What these infostealers take
Researchers who have taken apart the payloads from fake-interview repos describe infostealers and remote access tools. What they name:
- BeaverTail steals browser passwords on macOS and data from 13 cryptocurrency wallet browser extensions, including MetaMask, Phantom and Coinbase Wallet, on macOS and Windows. It then installs InvisibleFerret, which steals browser credentials and credit card details, uploads files from your user folders including .env files, logs keystrokes, and downloads the AnyDesk remote access client (Unit 42, 9 October 2024).
- Microsoft lists “API tokens, cloud credentials, signing keys, cryptocurrency wallets, and password manager artifacts”, naming KeePass databases, 1Password artifacts, wallet recovery phrases, environment files and source code. The OtterCookie backdoor also logs keystrokes, takes screenshots and watches the clipboard (Microsoft).
- Trend Micro found a remote access trojan, DEV#POPPER, that injects code into developer apps such as VS Code, Cursor, Discord, GitHub Desktop and Antigravity, and creates a hidden .node_modules folder. In the same campaign, attackers with access to a developer's machine injected obfuscated JavaScript into the victim's own repositories and rewrote git history to hide it; Trend Micro found the tool they used in at least 101 repositories (Trend Micro).
Two things follow. The list of what to rotate is long because the malware reads files, not just browser storage. And keylogging means anything you typed on that machine after the code ran, including a password manager's master password or an SSH key passphrase, counts as exposed.
From a clean device: revoke and rotate
Start with the accounts that can reset the others: your email, then your password manager's master password. Then work through this list. Rotating means making a new credential and killing the old one; only the second half stops an attacker.
| What | Where to kill the old one |
|---|---|
| GitHub | Settings: Sessions, Developer settings (tokens), SSH and GPG keys, Applications, Security log |
| npm | Profile picture, Access Tokens, or npm token revoke |
| AWS | IAM console: Users, your user, Security credentials, Access keys |
| Google Cloud | Google Account connected apps; service account keys with gcloud |
| Azure | Entra admin center: Revoke sessions; storage account keys: Regenerate |
| SSH | GitHub and GitLab key lists, and ~/.ssh/authorized_keys on every server |
| AI API keys | Claude Console API keys page; OpenAI API keys page |
| Browser logins | Each site's sign-out-everywhere control, then a new password |
| Crypto | Nothing to revoke: move funds to a new wallet |
Browser passwords, and the sessions behind them
Change every password your browser saved. That isn't the end of it. Stealing session cookies lets an attacker use an account without the password at all (Google Threat Analysis Group). Google says resetting a password or sign-in cookies doesn't invalidate access tokens an attacker already holds (Google Cloud), and Microsoft notes that a sign-in provider can't revoke a session an app issued on its own; the app has to (Microsoft Entra). So for each account, also end its sessions:
- Google: myaccount.google.com, Security & sign-in, Manage all devices, then Sign out of each one (Google).
- Microsoft account: Advanced security options, Sign out everywhere. It can take up to 24 hours and doesn't cover Xbox (Microsoft).
- GitHub: covered next.
- Anything else: look in its security settings for a sign-out-of-all-sessions control and use it.
GitHub
All of these are under your profile picture, then Settings:
- Sessions (under Access): revoke every web session except the one on your clean device, and any GitHub Mobile session you don't recognize (docs).
- Developer settings, Personal access tokens: open both Fine-grained tokens and Tokens (classic) and delete them. Deleting a token that created a deploy key deletes that key too (docs).
- SSH and GPG keys: delete every key that was on that machine, and any you don't recognize (docs).
- Applications (under Integrations): on Authorized OAuth Apps and Authorized GitHub Apps, revoke what you don't recognize, or use Revoke all and sign your tools back in later (OAuth apps, GitHub Apps). The GitHub CLI keeps its token in your system credential store, or in a plain text file if it can't use one (gh docs).
- Deploy keys: in each repository's settings, remove any you don't recognize (docs).
- Security log (under Archives): it covers the last 90 days. Look for tokens, SSH keys and OAuth authorizations created after the time you wrote down, and the countries they came from (docs).
Change your GitHub password too, and turn on two-factor authentication if it isn't on (docs).
Your own repositories
Because attackers in this campaign pushed code into victims' repos and rewrote history, check what you own and what you have push access to: recent force pushes, commits you don't remember, and config files that grew. Trend Micro says to search for the markers global['!'] and global['_V'] and for temp_auto_push.bat, and if you find them, to notify collaborators and anyone downstream (Trend Micro). On the clean machine, clone and search without opening the folder in an editor:
grep -rnE 'global\[.(!|_V).\]' --exclude-dir=node_modules . find . -name temp_auto_push.bat
Microsoft also advises reviewing recent access to your code repositories and CI/CD systems (Microsoft). Rotate any CI secret or signing key that was ever in a file on that machine.
npm
npm keeps your login token in ~/.npmrc as _authToken (npm docs). On npmjs.com, open your profile picture, then Access Tokens, and delete every token (npm docs). From a clean machine where you're logged in, the CLI does the same. The first command lists your tokens; the second revokes one by ID:
npm token list npm token revoke <id>
(npm token.) npm's guide says revocation can take up to an hour in some cases (npm docs). If you publish packages, check that no version appeared that you didn't publish.
AWS
Keys in the shared credentials file (~/.aws/credentials) are stored in plain text (AWS). In the IAM console, open Users, your user, Security credentials, and for each old access key choose Actions, Deactivate. Create a new key only when you have a clean machine to put it on. AWS's rotation guide waits before deleting an old key; for a stolen one, deactivate it now and delete it once nothing you run depends on it (AWS). The CLI equivalent, which switches the old key off:
aws iam list-access-keys --user-name YOUR_USER aws iam update-access-key --access-key-id OLD_KEY_ID --status Inactive --user-name YOUR_USER
Temporary credentials stay valid until they expire, up to 36 hours, so for roles you also have to change permissions or revoke the role's sessions; IAM Identity Center sessions are revoked in Identity Center (AWS). Then check CloudTrail for what the old keys did (AWS).
Google Cloud
Google's guide for compromised credentials says to remove Google Cloud CLI from your account's connected apps (your Google Account's linked apps page), and that a password reset alone doesn't cut off a stolen token (Google Cloud). For service account keys, disable the old key (this command switches it off; deleting comes after you've confirmed nothing uses it):
gcloud iam service-accounts keys list --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com
gcloud iam service-accounts keys disable KEY_ID \
--iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com --project=PROJECT_IDDisabling a key doesn't revoke short-lived credentials already issued from it; disabling the service account does (Google Cloud). API keys have a Rotate key button on the Credentials page (Google Cloud).
Azure
The Azure CLI stores a refresh token when you sign in with a user account (Microsoft). In a work tenant, an admin can open the user in the Entra admin center and choose Revoke sessions, or run Revoke-MgUserSignInSession; access tokens already issued last an hour by default (Microsoft Entra). Ask your admin rather than waiting it out. Storage account keys are regenerated under Security + networking, Access keys, or with az storage account keys renew, which also revokes SAS tokens signed with the old key (Microsoft).
SSH keys
Make a new key pair on the clean machine, with a passphrase (GitHub):
ssh-keygen -t ed25519 -C "you@example.com"
Then remove the old public key everywhere it was trusted: GitHub, GitLab, and the ~/.ssh/authorized_keys file on every server you log in to, which is the list of keys sshd accepts (sshd). A passphrase on the old key doesn't help if you typed it while a keylogger was running.
.env files, project secrets and AI API keys
InvisibleFerret collects .env files (Unit 42), so every secret in every project on that machine needs replacing, including ones that belong to your employer or clients. Tell them; it's their key to rotate too.
- Anthropic: in the Claude Console, open API keys, use the menu next to the key and choose Delete API key, then create a new one (Anthropic).
- OpenAI: keys are on the API keys page and usage on the Usage page; create a replacement and revoke the old key (OpenAI). Check usage for calls you didn't make.
Crypto wallets
A wallet's keys can't be revoked, only abandoned. MetaMask's own steps: install it in another browser or on another device, create a new wallet there, don't link the same Google or Apple account, write the new recovery phrase down, move what's left to it, and stop using the old phrase. If a sweeper script is draining the old address, don't send it more ETH for gas. Transactions can't be reversed (MetaMask). Create the new wallet on a device that never touched the repo, not in another profile on the infected machine.
Look for persistence
These checks tell you whether something is set to start again. They can't prove nothing is. Run them with the machine still offline, and read what each file runs.
macOS
Agents live in /Library/LaunchAgents and ~/Library/LaunchAgents, daemons in /Library/LaunchDaemons (Apple). Look for anything new, named after something you don't have, or pointing at a script in your home folder:
ls -la ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons
Then System Settings, General, Login Items & Extensions, for login items and apps allowed to run in the background (Apple).
Linux
crontab -l ls -la ~/.config/systemd/user systemd-analyze --user unit-paths
crontab -l prints your crontab (crontab). User units can live in several directories; the last command lists them all (systemd).
Shell startup files (macOS and Linux)
Read ~/.zshenv, ~/.zprofile, ~/.zshrc and ~/.zlogin (zsh), and ~/.bash_profile, ~/.bash_login, ~/.profile and ~/.bashrc (bash). A line you didn't write that runs node, curl or a file in a hidden folder runs again every time you open a terminal.
Windows
The Run and RunOnce keys start programs at logon (Microsoft), and Microsoft says FlexibleFerret persists through Run registry changes (Microsoft):
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run reg query HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run reg query HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce schtasks /query /fo LIST /v
The last command lists scheduled tasks in detail (Microsoft). Also open shell:startup and shell:common startup from the Run dialog, and Settings, Apps, Startup (Microsoft).
Editors and remote access tools
List your extensions and look for any you didn't install (VS Code CLI). They live in ~/.vscode/extensions (%USERPROFILE%\.vscode\extensions on Windows; VS Code); check Cursor's Extensions view the same way.
code --list-extensions --show-versions
A clean extension list isn't enough here: DEV#POPPER injects code into the editor apps themselves and leaves a hidden .node_modules folder (Trend Micro). That's one marker you can search for, not a full check:
find ~ -type d -name .node_modules 2>/dev/null
InvisibleFerret downloads AnyDesk (Unit 42), so treat a remote access app you never installed as a way back in for someone else.
Git config
A global core.hooksPath makes every repo on the machine use one hooks folder; a core.fsmonitor set to a path names a command git runs to check for changed files during commands like git status (true is the built-in monitor); core.sshCommand replaces ssh for fetch and push (git-config). Run this from your home folder, outside any repo, to see the system and global values and the file each came from:
git config --list --show-origin | grep -iE 'hookspath|fsmonitor|sshcommand'
Then go through the git hooks checks for each repo you worked in on that machine.
Decide on a reinstall
A full reinstall of the operating system is the only state you can be sure of. The malware in these campaigns modifies other apps and hides its own folders; finding nothing in the checks above means you didn't find it, not that it's gone. If you can, wipe it. If it's a work machine, your security team decides.
- Mac: System Settings, General, Transfer or Reset, Erase All Content and Settings, which erases all data, settings and apps. It needs macOS Monterey or later on Apple silicon or a T2 Mac; other Macs follow Apple's erase-and-reinstall route instead (Apple).
- Windows: Settings, System, Recovery, Reset PC, then Remove everything. Cloud download fetches a fresh copy of Windows rather than reusing the files on the PC (Microsoft).
- Linux: reinstall from a freshly downloaded image, and format the home partition rather than keeping it.
Before you wipe, copy off documents and photos only. Don't carry over apps, dotfiles, editor settings or extensions, and don't restore a full backup taken after the repo ran, because it brings back whatever was installed. Push code from the clean machine after reading the diff, not from the old one.
On the reinstalled machine, create fresh SSH keys and tokens rather than reusing anything you made while the old machine was still in use. Next time, run a stranger's code where losing the machine doesn't matter: a disposable VM with nothing on it.
Report it
- The repo and the account on GitHub: on the repository page, Report repository in the About sidebar; on the user's profile, Block or Report, then Report abuse (GitHub).
- The recruiter or client on LinkedIn: on their profile, More, Report / Block, then “This account is not a real person” or “This person is impersonating someone” (LinkedIn).
- An npm package it installed: Report malware on the package page (npm).
- In the US, file with the FBI's Internet Crime Complaint Center at ic3.gov, especially if money or crypto was taken. IC3 says it never contacts you for information or money and doesn't work with private firms to recover lost funds, so treat anyone offering to get your crypto back as a second scam.
- Your employer's security team if it was a work machine or touched work accounts, and your collaborators if your repos may have been changed.
What a repo checker can do now
Not much, and it's worth being plain about that. A static checker like the one I built at preclone.dev reads a repo without running it. It can't tell you what ran on your machine, what was taken, or whether anything is still there, and it doesn't clean anything. It also can't see what a script downloaded at run time, code inside binaries, or your dependencies' own source.
The one thing it can add after the fact: pasting the repo link on a clean device lists which files were set to run, and at which step (opening the folder, install, start, commit), with the file and line. That tells you whether opening the folder was already enough. The fake take-home example shows what that looks like. It's for the minute before you open the next one.
Questions
- I only opened the folder in VS Code. Do I need to do all of this?
- If you trusted the folder, or opened it in an editor with Workspace Trust turned off, a task set to run on folder open could have run without showing a terminal. Treat that the same as running it. If you stayed in Restricted Mode and ran nothing, automatic tasks didn't run, but read the repo's files from another device before you relax.
- Does changing my passwords log the attacker out?
- Not always. A stolen session cookie or access token can keep working after a password change. Use each service's sign-out-everywhere or revoke-sessions control as well, and revoke API tokens and keys separately.
- Will an antivirus scan clean it up?
- It may find and remove known files, and it's worth running. It can't tell you which passwords, tokens or wallet files were already copied, so you still have to rotate them, and a clean scan doesn't prove nothing is left.
- Someone says they can recover my stolen crypto for a fee. Should I pay?
- No. Blockchain transactions can't be reversed, and the FBI's IC3 says it never contacts victims for money and doesn't work with private firms to recover lost funds. Treat anyone offering to recover it as a second scam.
- How do I see whether my GitHub account was used?
- Open Settings, then Security log. It covers the last 90 days and shows events such as new personal access tokens, SSH keys and OAuth app authorizations, with the country they came from.
Check a repo before you open it
Paste a GitHub, GitLab or Bitbucket link. PreClone reads the repo without running it and lists what would run on your machine, by when it runs. Free for public repos, no login. It can miss things, so it never calls a repo safe.
Or see an example report first.
Related guides
- Fake job interview malware: how the take-home repo infects you, and what to check firstHow the fake recruiter take-home works, which repo files start the malware (tasks.json, configs, postinstall, git hooks) and what to do in the first minute.
- How to check a GitHub repo for malware before you clone itFake take-home repos run code on folder open or npm install. Which files to read first, which settings to change, and what to do if you already ran it.