How to compromise your system with a job interview
The current situation on the IT job market is hard. So you are lucky when a recruiter on LinkedIn reaches out to you having a suitable match for a new position based on your prior experience. It might not be what it seems at a first glance.
“A relevant opportunity” with part-time remote work and a great hourly compensation is what surely pulls a lot of current Software Engineers into the conversation when a new job offer on LinkedIn comes in - so it happened to a friend of mine. The job offer was matching very well with the former experience and paired with speeding up the interview process with a quickly sent coding challenge after a couple of messages on LinkedIn.
Info
The initial contact was made in the name of a company that did not know about this. So it is pure phishing just to steal your secrets and credentials. The company is well aware of that and already published a post on LinkedIn explaining the situation.
Before you start with the test, you might be suspicious about the following:
- The person contacting you is not part of the company on LinkedIn
- There is no first “Get to know you”-call before you receive the coding test
- The test might be in a different programming language than you’re skilled in
- The code is not available on a major Git platform
Hindsight is 20/20 so no judging here.
Now it begins
You needed to solve problems in an already existing codebase written in TypeScript. The project you receive is
- about 180 files
- a mix of dead and working code
- no obfuscation or minification
.. but with some calls to external https://api.jsonbin.io endpoints. If you did not read the 180 files of code, you are hooked.
Here is the fishy code part that starts downloading further packages and further scans your system.
Warning
That is the endpoint that ships more garbage. Watch out!
| |
The internal logic of the application always runs this function first by executing npm run dev, npm start, and so on. As it hands require in, it can:
require('child_process')for shell outrequire('fs')for read/walk the filesystem, write persistencerequire('net')/require('https')to open its own exfiltration channel- read
process.envdirectly, which in this app means MONGO_URI, JWT_SECRET, SENDGRID_API_KEY, CLOUDINARY_API_SECRET, PAYTM_MERCHANT_KEY
A lot of things you desperately do not want to happen on your system.
Some precaution for next time
A couple of things could have helped, although there is never a 100% protection. You would just not expect such a thing from a piece of code you get for a job opportunity.
- AI: Ask your AI of choice to scan the project for any anomalies - obfuscated code, minifications, calls to external endpoints, unusual code patterns, etc.
- Docker: Putting things into Docker and only executing the code inside isolates your host system and does not reveal any stored secret.
- Vagrant: Running the code in a completely isolated system might even be a better choice.
A note on the AI part: Claude Code was not able to detect any strange things when just prompted to scan the code base for unusual patterns.
What now
When the damage is done you probably should:
- revoke and rotate SSH keys
- change passwords
- check if you have any plaintext secrets or information stored that needs to be changed
… and reinstall your OS - better safe than sorry.
Meanwhile the fisherman’s (fake recruiter) profile has been deleted.
