Stop AI agents from installing packages that
don't exist.

AI coding agents hallucinate package names, and attackers register them. GhostDep checks every package before your agent installs it — inside IBM Bob, in the terminal, and in CI.

Caught in the wild

On 25 Sep 2026, GhostDep returned BLOCKED for reqeusts — a package first published three days earlier with five downloads, closely resembling requests. By the following day it was no longer on PyPI.

!
25 Sep 2026
GhostDep returns BLOCKED for reqeusts BLOCKED
First published 3 days earlier · 5 downloads · edit distance 2 from requests
✕
26 Sep 2026
reqeusts no longer available on PyPI REMOVED

Watching PyPI, live

reqeusts was spotted by chance. The Radar makes it systematic: every 30 minutes, GhostDep sweeps PyPI's feed of newly created packages and flags names that imitate one of the 1,000 most-downloaded packages.

Loading radar data… pypi.org/rss/packages.xml
—
new packages checked
—sweeps
—possible lookalikes
new packages per sweep now

Lookalikes are possible impersonations, not proof of malice; each one needs review. Sweeps are scheduled by GitHub Actions and can run a few minutes late. Raw data: radar/

Five checks, one verdict

GhostDep runs five deterministic checks. The most severe result becomes the verdict; a BLOCKED package is never installed.

Step 1
Agent requests a package
An AI agent generates a pip install command — could be a hallucinated name, a typo, or a real package.
Step 2
GhostDep runs 5 checks
Existence · Age · Popularity · Typosquatting (OSA distance vs top-5,000) · Vulnerabilities (OSV). Each check returns SAFE, SUSPICIOUS, or BLOCKED.
Step 3
Bob installs only what's safe
SAFE → install proceeds. SUSPICIOUS → flagged for review. BLOCKED → install refused; agent picks a real alternative.

Numbers that matter

Run on 2026-09-26 against 75 packages across four categories using the live PyPI registry. All names and results are fully reproducible (seed 42).

100%
Detection rate
(typosquats + hallucinated)
0%
False-positive rate
(popular + mid-popularity)
3/3
Historical attacks
detected (replay)
75
Packages tested
across 4 categories

Historical attacks (colourama, python3-dateutil, jeIlyfish) are simulated replays — those packages no longer exist on PyPI and are tested via the typosquat check directly. All 30 generated typosquats and hallucinated names were caught by the existence check; the typosquat check itself is evaluated in the historical replay. Full methodology and per-package results: benchmark/RESULTS.md

One tool, three surfaces

GhostDep plugs in at the exact moment a package name is chosen — whether that's inside an AI agent, a CI pipeline, or the command line.

IBM Bob (MCP server + skill + custom mode) AI agent
Register as an MCP server via Bob Settings → MCP → + (project scope), then activate the Dependency Guardian mode or the ghostdep-guard skill. While active, Bob checks every new package with check_package() before installing it.
// Bob MCP config (project scope)
{
  "mcpServers": {
    "ghostdep": {
      "command": "path/to/.venv/Scripts/python.exe",
      "args": ["-m", "ghostdep.server"],
      "cwd": "path/to/ghostdep"
    }
  }
}
CLI — check a single package or scan a whole file Command line
# Check, then install only if safe (drop-in for pip install)
ghostdep install requests python-dateutil

# Check one package
ghostdep check reqeusts

# Scan requirements.txt — exits 2 if any BLOCKED
ghostdep scan requirements.txt

# Generate a self-contained HTML report
ghostdep report requirements.txt --output report.html

# Watch the live PyPI feed for new lookalikes
ghostdep scan-new

# Allow internal packages, deny risky ones: .ghostdep.toml
[policy]
allow = ["acme-internal-auth"]
deny  = ["pycrypto"]
GitHub Actions CI gate CI/CD
Scans every PR that touches requirements.txt or pyproject.toml, uploads SARIF to the GitHub Security tab, and fails the job on BLOCKED packages.
# abridged
# .github/workflows/ghostdep.yml
on:
  pull_request:
    paths: ["requirements.txt", "pyproject.toml"]

jobs:
  ghostdep-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ghostdep scan requirements.txt --format sarif > ghostdep.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ghostdep.sarif