Project case study · 2026
interview-guard
A CLI that checks a take-home coding assessment repo for supply-chain scam patterns — malicious postinstall scripts, dependency confusion, typosquats — before you clone, install, or run anything a recruiter sent you.
The problem
There’s a real, ongoing scam — tracked by Microsoft, Socket, and ReversingLabs since 2023 under names like “Contagious Interview” — where fake recruiters send job seekers a “coding challenge” repo that’s actually malware. The pitch always looks legitimate: a real-sounding company, a normal GitHub repo, a standard-looking package.json. The payload is usually hidden in a dependency, or in a postinstall script that runs the moment you type npm install, often before you’ve opened a single file.
I built interview-guard as a second opinion before trusting a repo with your machine — a pre-flight check you run against the URL a recruiter sends you, before git clone or npm install ever touches it.
What it does
Given a GitHub URL, interview-guard reads public GitHub/npm data only — nothing gets cloned or executed — and returns a plain-language GREEN / YELLOW / RED verdict with the specific reasons behind it:
- Repo legitimacy — how old the repo is, star/fork count, commit history depth, and whether the owner is an established account or a fresh throwaway.
- Dependency safety — whether the repo’s own
package.jsonruns an install-time script (the #1 mechanism this scam uses), whether each dependency actually exists on npm, how recently it was published, how many people download it, and whether it has known advisories via OSV. - A sandbox escape hatch —
interview-guard sandbox <url>generates a throwaway, resource-capped Docker setup that clones and runs the repo inside a container, so a candidate who genuinely needs to run the assessment never exposes host SSH keys, credentials, or dotfiles to it.
Technical decisions
| Area | Decision |
|---|---|
| Dependencies | Zero runtime dependencies — plain fetch, hand-rolled ANSI colors, no framework |
| Distribution | Published to npm as interview-guard-cli (the plain interview-guard name was already taken by an unrelated package); the installed binary is still the short interview-guard |
| Data sources | GitHub REST API, the npm registry, npm’s downloads API, and OSV — all read-only, all public |
| Isolation | Sandbox mode clones inside the Docker image (no bind mounts), drops all capabilities, and publishes only to 127.0.0.1 |
| Testing | 97 tests via Node’s built-in node:test (still zero added dependencies) — boundary-tested severity thresholds, mocked fetch for every external API call, and full pipeline tests covering GREEN/RED verdicts and partial-API-outage resilience |
| CI | GitHub Actions runs the suite on every push/PR across Node 18, 20, and 22 |
What I learned
This was less about UI and more about designing a heuristic security tool that’s honest about its own limits: a GREEN verdict means no red flags were found, not a guarantee of safety, and the README says so explicitly. It was also a good exercise in testing code that’s mostly I/O — every GitHub/npm/OSV call is a bare fetch, which made mocking globalThis.fetch directly enough to get real coverage without adding a single test-framework dependency.
What’s next
Currently npm/Node.js only. Python (requirements.txt) support is the natural next ecosystem, since take-home assessments aren’t exclusively JavaScript.