{"id":50695723,"url":"https://github.com/hngprojects/lazarus-scanner","last_synced_at":"2026-06-09T06:08:26.656Z","repository":{"id":356877511,"uuid":"1234224491","full_name":"hngprojects/lazarus-scanner","owner":"hngprojects","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-10T07:09:23.000Z","size":19,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-10T09:20:48.210Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hngprojects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-09T22:51:54.000Z","updated_at":"2026-05-10T07:09:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hngprojects/lazarus-scanner","commit_stats":null,"previous_names":["hngprojects/lazarus-scanner"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hngprojects/lazarus-scanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Flazarus-scanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Flazarus-scanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Flazarus-scanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Flazarus-scanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hngprojects","download_url":"https://codeload.github.com/hngprojects/lazarus-scanner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Flazarus-scanner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34093840,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-09T06:08:25.894Z","updated_at":"2026-06-09T06:08:26.649Z","avatar_url":"https://github.com/hngprojects.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lazarus Config-Injection Scanner\n\nCross-platform Python scanner + safeguarder for the **Contagious Interview**\n/ **BeaverTail** supply-chain attack that hides obfuscated payloads in\nJavaScript config files (`next.config.js`, `postcss.config.js`, etc.).\n\nThree modes of operation, all in one tool:\n\n1. **Detect** — find the malware in files, processes, and persistence locations.\n2. **Remediate** — quarantine + clean infected files, kill malicious processes.\n3. **Harden** — apply proactive defenses so reinfection is harder.\n\nReference: [GitHub Community discussion #188732](https://github.com/orgs/community/discussions/188732#discussioncomment-16368443)\n\n---\n\n## What it detects\n\n**Files** — every `*.config.{js,mjs,cjs,ts}` in the tree (matches `next`, `postcss`, `tailwind`, `vite`, `webpack`, `rollup`, `svelte`, `astro`, `nuxt`, `remix`, `babel`, `vue`, `jest`, `playwright`, `cypress`, `prettier`, `commitlint`, `lint-staged`, `metro`, …) plus `gatsby-config.*`, `gatsby-node.*`, `.babelrc.{js,cjs,mjs}`, `babel.config.json`:\n- IOC strings: `global['!']`, `_$_1e42`, `A4-1928`, `TronWeb`, `bsc-dataseed`, `api.trongrid.io`, ethers JsonRpcProvider, Solana keypair access, macOS keychain refs, Chrome creds paths\n- Whitespace-padding tricks (\u003e200 spaces/tabs on one line)\n- `eval()` calls in config files\n- Long encoded blobs (\u003e=500 chars)\n- Suspicious large configs (\u003e8 KB combined with `eval`)\n\n**Processes** (any `node` / `bun` / `electron` process):\n- TRON / BSC RPC endpoints in cmdline\n- Obfuscation markers in cmdline\n- Running from `/tmp`, `/var/tmp`, `/dev/shm`, `%TEMP%`, `\\Windows\\Temp\\`, `/private/tmp`\n- Detached (ppid=1) node processes\n- `eval(`/`atob(` in cmdline\n- Hex blobs in cmdline (\u003e=200 hex chars)\n- Cmdlines longer than 1500 chars (likely encoded payload)\n\nA process is flagged if its **suspicion score \u003e= 2**. Each indicator is worth 1–2 points; multiple weak signals combine.\n\n**Persistence** (cross-platform):\n- `curl|wget … | node|sh|bash|powershell` in `.bashrc`, `.bash_profile`, `.profile`, `.zshrc`, `.zprofile`, fish config\n- User crontab entries calling node/curl/wget (Linux/macOS)\n- LaunchAgents referencing node/curl (macOS `~/Library/LaunchAgents/*.plist`)\n- Scheduled Tasks referencing node/curl (Windows)\n- Registry Run keys with node/curl/encoded PowerShell (Windows `HKCU\\…\\Run`)\n\n## Requirements\n\n- Python 3.8+ — standard library only, no `pip install` required.\n  - Linux/macOS: usually preinstalled.\n  - Windows: `winget install Python.Python.3.12` or grab from python.org.\n\n## Quick start\n\n### Linux / macOS\n\n```bash\n# Detection only — scan the current directory\npython3 lazarus_scanner.py\n\n# Scan a specific folder\npython3 lazarus_scanner.py ~/Documents/gigs\n\n# Scan everything under your home dir\npython3 lazarus_scanner.py --scan-home\n\n# Detect AND clean infected files (auto-backs-up first)\npython3 lazarus_scanner.py --scan-home --fix\n\n# Detect AND kill suspicious processes (asks per-process)\npython3 lazarus_scanner.py --kill\n\n# Apply proactive defenses (npm ignore-scripts, hosts hint, etc.)\npython3 lazarus_scanner.py --harden\n\n# Do everything: scan home + clean files + kill procs + harden\npython3 lazarus_scanner.py --all\n\n# Continuous monitoring (checks every 60s, Ctrl-C to stop)\npython3 lazarus_scanner.py --watch --interval 60 --log ~/lazarus.log\n```\n\n### Windows (PowerShell or cmd)\n\n```powershell\npy -3 lazarus_scanner.py\npy -3 lazarus_scanner.py --scan-home --fix\npy -3 lazarus_scanner.py --kill\npy -3 lazarus_scanner.py --harden\npy -3 lazarus_scanner.py --all\n```\n\n## Flags\n\n| Flag | Purpose |\n|---|---|\n| `paths…` | Directories to scan (default: current dir) |\n| `--scan-home` | Also scan `$HOME` / `%USERPROFILE%` |\n| `--fix` | Quarantine each hit (`\u003cfile\u003e.malware-backup-\u003cts\u003e`) and truncate the trailing payload |\n| `--kill` | Kill suspicious processes — asks for confirmation per PID |\n| `--harden` | Apply proactive defenses (see below) |\n| `--all` | Equivalent to `--scan-home --fix --kill --harden` |\n| `--yes` / `-y` | Skip confirmation prompts (use with care) |\n| `--watch` | Continuous loop — re-scan every `--interval` seconds |\n| `--interval N` | Watch interval in seconds (default 60) |\n| `--json` | Machine-readable output |\n| `--no-process-check` | Skip running-process inspection (faster) |\n| `--log FILE` | Append each run's JSON report to `FILE` (audit trail) |\n\nExit code is `1` if anything suspicious was found, `0` otherwise — usable in CI / pre-commit / cron.\n\n## What each remediation actually does\n\n### `--fix` (config files)\n\n1. Copies the file to `\u003cfile\u003e.malware-backup-\u003cunix-timestamp\u003e` (preserves mtime).\n2. Searches for the **first** legitimate end marker:\n   - `export default \u003cname\u003e;`\n   - `module.exports = \u003cname\u003e;`\n   - `export default { … };`\n   - `module.exports = { … };`\n3. Truncates everything after that point and writes a single trailing newline.\n4. Skips files where it can't find a clean cut point — better to bail than corrupt.\n\n### `--kill` (processes)\n\n1. Lists every running process scored ≥ 2.\n2. For each: prints `pid`, `ppid`, score, indicators, and a 80-char cmdline preview.\n3. Asks `[y/N]` per process (skip with `--yes`).\n4. POSIX: `kill -9 \u003cpid\u003e`.  Windows: `taskkill /F /PID \u003cpid\u003e`.\n\n### `--harden` (proactive defenses)\n\n1. Sets `npm config set ignore-scripts true` globally — blocks the `postinstall` vector. Revert with `npm config delete ignore-scripts`.\n2. Runs `git credential-cache exit` — flushes any in-memory cached git credentials, so a backgrounded malicious process can't borrow them.\n3. Checks your hosts file for entries blocking known C2 domains and **prints the lines you should add as root/admin**:\n   - `api.trongrid.io`, `api.shasta.trongrid.io`, `api.nileex.io`\n   - `bsc-dataseed.binance.org`, `bsc-dataseed1.defibit.io`, `bsc-dataseed1.ninicoin.io`\n   - `data-seed-prebsc-1-s1.binance.org`, `data-seed-prebsc-2-s1.binance.org`\n\n   The hosts file is **not auto-edited** because it requires elevation and is system-critical. Append manually:\n\n   ```bash\n   # Linux / macOS\n   sudo sh -c 'cat \u003e\u003e /etc/hosts \u003c\u003cEOF\n   127.0.0.1\tapi.trongrid.io\n   127.0.0.1\tbsc-dataseed.binance.org\n   # …rest of the lines printed by --harden\n   EOF'\n   ```\n\n   ```powershell\n   # Windows — run PowerShell as Administrator\n   Add-Content -Path \"$env:WINDIR\\System32\\drivers\\etc\\hosts\" -Value \"127.0.0.1`tapi.trongrid.io\"\n   ```\n\n\u003e Note: blocking BSC / TRON RPC endpoints will break legitimate Web3 work. If you build crypto apps, skip the hosts step or block selectively.\n\n## Watch mode\n\n`--watch` runs the same checks on a loop. Pair it with `--log` to keep an audit trail:\n\n```bash\npython3 lazarus_scanner.py --watch --interval 30 --log ~/lazarus-audit.jsonl\n```\n\nEach run appends one JSON line. To run it as a background daemon:\n\n```bash\nnohup python3 lazarus_scanner.py --watch --interval 60 \\\n  --log ~/lazarus-audit.jsonl --no-process-check \u003e/dev/null 2\u003e\u00261 \u0026\n```\n\nOr as a cron / systemd-timer / Task Scheduler entry — exit code `1` flags hits for alerting.\n\n## If something is found\n\n1. **Stop**. Don't run `npm install`, `npm run dev`, or push commits until you've cleaned up.\n2. Inspect the backup the scanner saved next to each infected file — confirm the indicators are real (not a false positive on, say, a legitimate Web3 config).\n3. Run `--fix` to clean automatically, or restore from the last clean git commit: `git checkout HEAD -- next.config.js`.\n4. Run `--kill` to terminate any matched malicious processes.\n5. Run `--harden` to set defenses and print the hosts entries.\n6. Rotate every credential the host had access to:\n   - `gh auth status` → revoke and re-issue.\n   - `npm token list` → revoke.\n   - SSH keys, `.env` secrets, browser-saved creds, **crypto wallet seed phrases**.\n7. Audit your repos for unauthorized commits:\n   ```bash\n   for d in */; do\n     (cd \"$d\" \u0026\u0026 git log --all --since=\"2025-11-01\" --pretty=format:\"%h %an %ae %s\" 2\u003e/dev/null) \\\n       | sed \"s|^|$d: |\"\n   done\n   ```\n8. Reboot — the report says hidden detached processes survive until reboot but not past it.\n9. Consider the host compromised. The only fully safe move is a wipe; at minimum reboot, re-scan, harden, and watch for reappearance.\n\n## Defenses going forward\n\n- Run interview coding tests in a **VM, container, or sandbox** — never on your host.\n- Use a separate user account / machine for freelance / contract work.\n- Pin and review `postinstall` scripts in `package.json` of any cloned repo.\n- Keep `npm config set ignore-scripts true` set; opt in per project when needed.\n- Schedule `python3 lazarus_scanner.py --scan-home` to run daily via cron / Task Scheduler with `--log` for an audit trail.\n- Keep recent clean snapshots / backups so you can restore quickly.\n\n## Files\n\n```\nlazarus-scanner/\n├── lazarus_scanner.py    # the scanner (stdlib only)\n└── README.md             # this file\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhngprojects%2Flazarus-scanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhngprojects%2Flazarus-scanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhngprojects%2Flazarus-scanner/lists"}