Metadata-Version: 2.5
Name: pincheck
Version: 0.1.0
Summary: Supply-chain gate for requirements.txt: OSV vulnerabilities, malware advisories, and a release-age cooldown.
Project-URL: Homepage, https://github.com/ParisNeo/pincheck
Project-URL: Issues, https://github.com/ParisNeo/pincheck/issues
Author: ParisNeo
License-Expression: MIT
License-File: LICENSE
Keywords: cooldown,malware,osv,pypi,requirements,security,supply-chain
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Description-Content-Type: text/markdown

# pincheck

Supply-chain gate for `requirements.txt`. Stdlib only, zero dependencies.

For every pinned package (`name==version`) it checks:

1. **Vulnerabilities** — advisories on [OSV.dev](https://osv.dev) for that exact version.
2. **Malware** — OSV `MAL-*` advisories (OpenSSF malicious-packages feed).
3. **Cooldown** — fails if the release is younger than N hours (default 48), so you never install
   something the community hasn't had time to analyse.
4. **Yanked** releases.

```
pip install pincheck
pincheck requirements.txt
pincheck requirements.txt --hours 72 --json
pincheck base.txt dev.txt --ignore GHSA-xxxx-xxxx-xxxx
pip freeze | pincheck -
```

## Exit codes

| code | meaning |
|---|---|
| 0 | clean |
| 1 | malware **or** release younger than cooldown |
| 2 | known vulnerabilities, yanked, or unverifiable release |
| 3 | usage / network error |

## CI

```yaml
- run: pip install pincheck && pincheck requirements.txt --hours 72
```

## Limits

- Only exact pins (`==`) are checked; unpinned lines are listed, not silently passed.
  Check a fully resolved file (`pip-compile`, `uv pip compile`, `pip freeze`) to cover transitive deps.
- A clean OSV result on a brand-new release proves nothing: OSV lags. That is what the cooldown is for.
- It checks the release you pin, not whether your index/mirror serves the same bytes. Use `--require-hashes` for that.
- PyPI only.

MIT licensed.
