Metadata-Version: 2.4
Name: wary-sh
Version: 0.1.0
Summary: Verify a package is real before you install it — built for the AI-coding era of typosquatting and slopsquatting.
License: MIT
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# wary

Verify a package is real — and isn't a typosquat — before you install it.

```
$ wary check requsts --ecosystem pypi
  💀 requsts [pypi] — nonexistent
      → 'requsts' does not exist on pypi. If an AI assistant suggested this
        package, it's a hallucinated name — do not install it.

  1 packages checked — 0 ok, 0 suspicious, 0 likely squats, 1 nonexistent
  RESULT: FAIL
```

## Why this exists

AI coding assistants are extremely good at writing code and occasionally hallucinate a package name that sounds exactly right and doesn't exist. Security researchers call this **slopsquatting**: attackers watch for these hallucinated names — Copilot, ChatGPT, and Claude all tend to hallucinate the *same* plausible-sounding names repeatedly — and register them first, so the next developer who blindly installs what their AI suggested gets malware instead.

This isn't hypothetical. 2026 alone has seen a steady drumbeat of real supply-chain compromises: the Axios npm hijack (100M+ weekly downloads, North Korea-attributed), the LiteLLM PyPI poisoning, a compromised Red Hat npm namespace, a fake `@bitwarden/cli` impersonating the real Bitwarden CLI, and typosquatted OpenSearch/DevOps packages harvesting AWS and CI/CD credentials. Every one of these relied on the same thing: a developer (or a CI pipeline) installing a name that looked right.

Excellent general supply-chain-security tools exist (Socket.dev, Snyk) — but they're built and priced for teams of 5+ developers. `wary` is narrower and free at the individual level: **is this specific name I'm about to install real, and does it look like it's impersonating something popular.**

## Install

```bash
pip install wary
```

## Use it the moment it matters

Right after your AI assistant suggests a package, before you run the install:

```bash
wary check some-package-suggested-by-copilot --ecosystem npm
```

## Scan a whole project

```bash
cd your-project
wary scan
```

## Check only what's new (the CI use case)

```bash
wary diff /path/to/base-branch-checkout /path/to/pr-branch-checkout
```

This is what the GitHub Action runs on every PR — see [`action/README.md`](action/README.md). It only flags dependencies that are new in the diff, so it's quiet on unrelated PRs and loud exactly when something new shows up.

## What it checks

For every package name:

1. **Does it exist at all?** If not, and this came from an AI suggestion, it's a hallucination — the single most actionable finding `wary` produces.
2. **Is the name a squat pattern** against one of ~650 popular npm/PyPI packages — character swaps, keyboard-adjacent typos, combosquats (`lodash-utils`), delimiter swaps (`react_dom`), pluralization, vowel swaps?
3. **Is it young enough to be an active impersonation** rather than a coincidentally similar independent package?
4. **Does its publish history look automated** — a burst of many versions in a very short window?

See [`docs/DETECTION.md`](docs/DETECTION.md) for the full pattern taxonomy and the verdict logic.

## Limitations (read this)

- This is a fast, automated first pass, not a guarantee. A package that passes every check here can still be malicious in ways that don't show up in name similarity or publish timing (a legitimately-named package whose maintainer's account gets compromised, for instance — exactly what happened to Axios).
- The protected-name list (`src/wary/popular_names.py`) is a curated, versioned snapshot of ~650 packages, not a live top-N-by-downloads query — see the file for why.
- Currently covers npm and PyPI. See [`docs/ROADMAP.md`](docs/ROADMAP.md) for what's next.

## Development

```bash
pip install -e ".[dev]"
pytest                    # unit tests (fast, offline)
pytest -m integration     # + live tests against real npm/PyPI registries
```

## License

MIT — see [`LICENSE`](LICENSE).
