A fake client slipped a malicious GitHub repository into my inbox this week, and simply running the starter script wiped two days of work and exposed every password I keep in my browser.
The “client” posted a high-paying senior-engineer role, messaged quickly, and sent a polished-looking repo. The request was simple: clone, run npm run dev, and send a screenshot to prove the demo works—no contract, no background check. The moment the dev server started, hidden code in a configuration file reached out to a command-and-control (C2) server, fetched a second-stage payload and began siphoning credentials from the local machine.
How the attack unfolded
The malicious payload lived in postcss.config.js, a file most developers glance over because it usually contains a handful of simple CSS processing rules. In this case the attacker appended a line of obfuscated JavaScript far to the right of a legitimate statement, padded with spaces to blend in. When the npm run dev command executed the PostCSS pipeline, the hidden line ran unnoticed.
The malware performed three steps in rapid succession:
- C2 contact – it opened a network connection to an attacker-controlled server and announced the compromised host.
- Second-stage download – it pulled additional code that contained the real data-exfiltration logic.
- Browser credential theft – on macOS it queried the Chrome Safe Storage key stored in the system keychain. If the user approved the keychain prompt, the attacker harvested every password saved in Chrome.
Beyond the immediate theft, the payload wrote itself into several common developer tools—VS Code, npm, Discord—so that any future launch of those applications re-instantiated the malicious code. A simple reboot did not clear the infection; the next npm install or opening of the editor revived the backdoor.
Red flags that often go unnoticed
- Requests to run code before any contract is signed. Legitimate hiring processes usually involve a formal agreement before any proprietary work is shared.
- Compressed files masquerading as “project briefs.” Zip or RAR archives can hide executable scripts or malicious binaries.
- Requests for personal email addresses to “bypass platform filters.” This ploy moves the conversation off the protected platform where abuse can be reported.
- Job descriptions that ask the candidate to fund a crypto wallet or purchase test tokens. Such demands are atypical for genuine development work.
Practical steps to stay safe
- Never execute a stranger’s code without inspection. Open the repository in a read-only view (e.g., via the raw file view on GitHub) and scan every script, especially configuration files and
package.jsonscriptsentries. - Treat all attachments as plain text. If a zip file is sent, extract it in a sandboxed environment and examine the contents before opening anything.
- Use a dedicated password manager instead of browser storage. Even if a browser’s keychain is compromised, the manager’s vault stays isolated.
- Run untrusted code in an isolated virtual machine or container with no network access. This blocks the attacker’s ability to reach a C2 server.
- Enable two-factor authentication (2FA) on all accounts. If a password is stolen, the second factor stops unauthorized logins.
- Keep developer tools up to date and enable automatic integrity checks where available. Some editors now warn when core files are modified unexpectedly.
If you suspect you have run malicious code, assume the system is compromised. Back up essential data, wipe the drive, and reinstall the operating system. A simple reboot will not eradicate a persistence mechanism that rewrites files in common apps.
Bottom line: a single line of hidden JavaScript can turn a routine demo into a full-blown credential theft operation. Treat every repository as untrusted until you’ve verified it, and make isolation a default part of your workflow. The cost of a moment’s haste far outweighs the effort spent double-checking a file.
