mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
* feat: add GitHub Action for one-step PMG setup in CI
Composite action at repo root that downloads PMG (with SHA-256 verification
against the upstream checksums.txt), runs `pmg setup install`, and wires
shims onto $GITHUB_PATH so subsequent `npm install` / `pip install` calls
are transparently analyzed.
Defaults are conservative: malware blocking + dependency cooldown + proxy
mode (matching PMG's own defaults). Sandbox is opt-in because enabling
Landlock/Bubblewrap on ubuntu-latest requires relaxing AppArmor
user-namespace restrictions.
Cloud sync uses the documented SAFEDEP_API_KEY / SAFEDEP_TENANT_ID env-var
fallback so we skip the keychain codepath that has no usable backend in
headless CI. When cloud is enabled and no endpoint-id is supplied, the
action sets PMG_CLOUD_ENDPOINT_ID=github-actions/${GITHUB_REPOSITORY} so
events aggregate per repository instead of per ephemeral runner hostname.
Closes #248.
https://claude.ai/code/session_01ARb8ZiBiJjvhWjchBXraAh
* fix(action): drop github.repository template from input description
Action manifest validation rejected the action.yml because the endpoint-id
input description contained ${{ github.repository }} — template expressions
aren't evaluated in input description text and trip the validator with
"Unrecognized named-value: 'github'". This caused every job using uses: ./
to fail before any step ran.
Also switch the config-file e2e job to verify the staged file directly
instead of calling `pmg config get`, which is not in the v0.13.0 release
that "latest" resolves to today.
https://claude.ai/code/session_01ARb8ZiBiJjvhWjchBXraAh
* fix(action): address review comments on PR #263
- Drop opinionated defaults on PMG_* toggle inputs. All defaults are now
empty strings, and the action only exports PMG_* env vars when the
caller explicitly sets the input. Without this, defaults like
PMG_PARANOID=false silently shadowed config-file overrides because env
vars beat config.yml in Viper precedence.
- Verify cached PMG against upstream checksums.txt on every cache hit.
The cached tarball is stored alongside the binary and re-hashed against
the freshly-fetched checksums.txt; on drift, the cache entry is evicted
and re-downloaded.
- Export PMG_* env vars BEFORE running `pmg setup install` so settings
like disable-telemetry actually apply during setup, not just to
subsequent package-manager calls.
- Add `|| true` to the grep that extracts the expected checksum so
set -e doesn't kill the script before the friendly error message fires
when no checksum entry is found.
- Pin third-party actions (actions/checkout, actions/setup-node) to
commit SHAs to match the repo's supply-chain hardening convention.
- Fix the malicious-package E2E test capturing tee's exit code instead
of npm's; redirect to a file and check the actual command exit code.
- Add an E2E job that asserts PMG_PARANOID is unset when only
config-file is provided — regression guard for the precedence fix.
https://claude.ai/code/session_01ARb8ZiBiJjvhWjchBXraAh
* ci(action-e2e): scope sandbox tests to action setup, not PMG runtime
The landlock job was running `npm install express` with no explicit
sandbox profile and the default profile blocks something npm needs
(PMG's own e2e uses `--sandbox-profile npm-restrictive` to make this
viable). Bubblewrap happened to pass, but verifying the default sandbox
profile is permissive enough for arbitrary package installs is PMG's
e2e responsibility — this workflow's job is to assert the action wires
sandbox config correctly.
Switch both drivers to a matrix and verify only what the action owns:
PMG_SANDBOX_* env vars propagated, pmg binary runs, bwrap is installed
when requested, AppArmor user-ns restriction relaxed.
https://claude.ai/code/session_01ARb8ZiBiJjvhWjchBXraAh
* ci(action-e2e): bump setup-node to 24
Node 20 reached end-of-life and setup-node now warns on it. Match the
version pinned by publish-npm.yml (the repo's newest workflow). Updated
the README and docs/github-action.md quick-start examples to match.
https://claude.ai/code/session_01ARb8ZiBiJjvhWjchBXraAh
---------
Co-authored-by: Claude <noreply@anthropic.com>
270 lines
9.8 KiB
Markdown
270 lines
9.8 KiB
Markdown
<div align="center">
|
|
<img src="./docs/assets/pmg-banner.png" alt="PMG GitHub Banner">
|
|
</div>
|
|
<br/>
|
|
|
|
<div align="center">
|
|
<h1>Package Manager Guard (PMG)</h1>
|
|
</div>
|
|
|
|
<div align="center">
|
|
|
|
[](https://docs.safedep.io/pmg/quickstart)
|
|
[](https://safedep.io)
|
|
[](https://discord.gg/kAGEj25dCn)
|
|
|
|
[](https://goreportcard.com/report/github.com/safedep/pmg)
|
|

|
|

|
|
[](https://api.securityscorecards.dev/projects/github.com/safedep/pmg)
|
|
[](https://github.com/safedep/pmg/actions/workflows/codeql.yml)
|
|
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div align="center">
|
|
<img src="./docs/demo/pmg-intro.gif" width="800" alt="pmg in action">
|
|
</div>
|
|
|
|
## Why PMG?
|
|
|
|
Developers and AI coding agents install packages every day. Each `npm install` or `pip install` executes thousands of lines of code that nobody reviews.
|
|
|
|
Malicious packages ship constantly in popular ecosystems:
|
|
|
|
- [**litellm 1.82.8**](https://safedep.io/malicious-litellm-1-82-8-analysis/) - a popular AI proxy library compromised to exfiltrate credentials
|
|
- [**telnyx 4.87.2**](https://safedep.io/malicious-telnyx-pypi-compromise/) - a legitimate telecom SDK hijacked on PyPI
|
|
- [**pino-sdk-v2**](https://safedep.io/malicious-npm-package-pino-sdk-v2-env-exfiltration/) - a typosquat package disguised as the popular pino logger
|
|
|
|
PMG intercepts every package install and checks it for malware **before** code executes. Install it once, and every `npm install`, `pip install`, and `poetry add` is protected automatically.
|
|
|
|
> Featured in [tl;dr sec](https://tldrsec.com/p/tldr-sec-316) and used by engineering teams worldwide.
|
|
|
|
## How PMG Works
|
|
|
|
- **Transparent Protection** - PMG wraps `npm`, `pip`, and other package managers to transparently apply protection. Developers and AI agents use their tools as usual with no workflow changes.
|
|
- **Malicious Package Protection** - Every intercepted package is analyzed against [SafeDep's real-time threat intelligence](https://safedep.io) before installation. Malicious packages are blocked before code executes on the system.
|
|
- **Sandboxed Installation** - Package installation runs inside OS-native sandboxes (macOS Seatbelt, Linux Bubblewrap), preventing install scripts from modifying the system even if a threat evades detection.
|
|
- **Audit Logging** - Every package installation event is logged, providing a verifiable trail of what was installed, when, and from where.
|
|
|
|
## Quick Start
|
|
|
|
Get protected in seconds.
|
|
|
|
### 1. Install
|
|
|
|
**MacOS / Linux (Install Script)**
|
|
|
|
```bash
|
|
curl -fsSL https://raw.githubusercontent.com/safedep/pmg/main/install.sh | sh
|
|
```
|
|
|
|
**MacOS / Linux (Homebrew)**
|
|
|
|
```bash
|
|
brew install safedep/tap/pmg
|
|
```
|
|
|
|
**NPM**
|
|
|
|
```bash
|
|
npm install -g @safedep/pmg
|
|
```
|
|
|
|
> **Note:** NPM-based installs can be fragile when Node.js is managed by version managers like [`mise`](https://mise.jdx.dev/) or [`asdf`](https://asdf-vm.com/), since the global `npm` bin path changes with the active Node version. Prefer the install script or Homebrew in those setups.
|
|
|
|
> See [Installation](#installation) for additional methods.
|
|
|
|
### 2. Setup
|
|
|
|
Configure your shell to use PMG automatically.
|
|
|
|
```bash
|
|
pmg setup install
|
|
# Restart your terminal to apply changes
|
|
```
|
|
|
|
> **Tip:** Re-run `pmg setup install` after upgrading PMG to pick up new configuration options.
|
|
|
|
### 3. Use
|
|
|
|
Use your package managers as usual or let your AI coding agent use them. PMG works silently in the background.
|
|
|
|
```bash
|
|
npm install express
|
|
# or
|
|
pip install requests
|
|
```
|
|
|
|
Verify PMG is working by installing a test package. This is a harmless package flagged as malicious in the SafeDep database, specifically meant for testing:
|
|
|
|
```bash
|
|
npm --prefer-online --no-cache i safedep-test-pkg@0.1.3
|
|
```
|
|
|
|
<details>
|
|
<summary>Expected output</summary>
|
|
|
|
```
|
|
✗ Malicious package blocked
|
|
|
|
- safedep-test-pkg@0.1.3
|
|
Reference: https://app.safedep.io/community/malysis/01KF5JYDND9XR94WNEJ2G74KY2
|
|
|
|
✗ PMG: 1 packages analyzed, 1 blocked
|
|
```
|
|
|
|
</details>
|
|
|
|
## Features
|
|
|
|
| Feature | Description |
|
|
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
| **AI Agent Safety Net** | Protects against malicious packages installed by AI coding agents (Claude Code, Cursor, Copilot, Windsurf). |
|
|
| **Malicious Package Protection** | Real-time protection against malicious packages using [SafeDep](https://docs.safedep.io/cloud/malware-analysis). |
|
|
| **Sandboxing** | Enforces least privilege using OS native sandboxing to contain installation scripts. |
|
|
| **Dependency Analysis** | Deep scans of direct and transitive dependencies before they hit your disk. |
|
|
| **Event Logging** | Keeps a verifiable audit trail of all installed packages. |
|
|
| **Dependency Cooldown** | Blocks package versions published within a configurable time window, reducing exposure to supply chain attacks. |
|
|
| **Zero Config** | Works out of the box with sensible security defaults. |
|
|
| **Cross-Shell** | Seamlessly integrates with Zsh, Bash, Fish, and more. |
|
|
|
|
## Supported Package Managers
|
|
|
|
PMG supports the tools you already use:
|
|
|
|
| Ecosystem | Tools | Status | Command Example |
|
|
| ----------- | -------- | ------ | ------------------- |
|
|
| **Node.js** | `npm` | Yes | `npm install <pkg>` |
|
|
| | `pnpm` | Yes | `pnpm add <pkg>` |
|
|
| | `yarn` | Yes | `yarn add <pkg>` |
|
|
| | `bun` | Yes | `bun add <pkg>` |
|
|
| | `npx` | Yes | `npx <pkg>` |
|
|
| | `pnpx` | Yes | `pnpx <pkg>` |
|
|
| **Python** | `pip` | Yes | `pip install <pkg>` |
|
|
| | `poetry` | Yes | `poetry add <pkg>` |
|
|
| | `uv` | Yes | `uv add <pkg>` |
|
|
|
|
## Installation
|
|
|
|
<details>
|
|
<summary><strong>Install Script (MacOS/Linux)</strong></summary>
|
|
|
|
Downloads the latest release from GitHub, verifies its SHA-256 checksum, and installs to `$HOME/.local/bin` (if on `PATH`) or `/usr/local/bin`.
|
|
|
|
```bash
|
|
curl -fsSL https://raw.githubusercontent.com/safedep/pmg/main/install.sh | sh
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Homebrew (MacOS/Linux)</strong></summary>
|
|
|
|
```bash
|
|
brew tap safedep/tap
|
|
brew install safedep/tap/pmg
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>NPM (Cross-Platform)</strong></summary>
|
|
|
|
```bash
|
|
npm install -g @safedep/pmg
|
|
```
|
|
|
|
> **Note:** NPM-based installs can be fragile when Node.js is managed by version managers like [`mise`](https://mise.jdx.dev/) or [`asdf`](https://asdf-vm.com/). The global `npm` bin path changes with the active Node version, so switching versions can leave `pmg` unavailable on `PATH` (or pointing to an old install). For these setups, prefer the install script or Homebrew.
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Go (Build from Source)</strong></summary>
|
|
|
|
```bash
|
|
# Ensure $(go env GOPATH)/bin is in your $PATH
|
|
go install github.com/safedep/pmg@latest
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Binary Download</strong></summary>
|
|
|
|
Download the latest binary for your platform from the [Releases Page](https://github.com/safedep/pmg/releases).
|
|
</details>
|
|
|
|
## GitHub Actions
|
|
|
|
Protect your CI workflows by adding a single step. Every `npm install`,
|
|
`pip install`, etc. in the job is transparently analyzed by PMG.
|
|
|
|
```yaml
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 24
|
|
- uses: safedep/pmg@v1
|
|
- run: npm ci
|
|
```
|
|
|
|
Zero-config users get malware blocking and dependency cooldown out of the
|
|
box. Power users tune behavior via inputs (`paranoid`, `sandbox`,
|
|
`cooldown-days`, ...) or by pointing `config-file` at a YAML in the repo.
|
|
See [docs/github-action.md](docs/github-action.md) for the full reference.
|
|
|
|
## Uninstallation
|
|
|
|
Remove shell integration:
|
|
|
|
```bash
|
|
pmg setup remove
|
|
```
|
|
|
|
To also remove the PMG configuration file:
|
|
|
|
```bash
|
|
pmg setup remove --config-file
|
|
```
|
|
|
|
Then uninstall PMG itself:
|
|
|
|
```bash
|
|
# Homebrew
|
|
brew uninstall safedep/tap/pmg
|
|
|
|
# NPM
|
|
npm uninstall -g @safedep/pmg
|
|
```
|
|
|
|
## Trust and Security
|
|
|
|
Security is our first class requirement. PMG builds are reproducible and signed.
|
|
|
|
* **Attestations**: GitHub and npm attestations are used to guarantee artifact integrity.
|
|
* **Verification**: Users can cryptographically prove the binary matches the source code.
|
|
* See [Trusting PMG](docs/trust.md) for verification steps.
|
|
|
|
## User Guide
|
|
|
|
* [Trusted Packages Configuration](docs/trusted-packages.md)
|
|
* [Dependency Cooldown](docs/dependency-cooldown.md)
|
|
* [Proxy Mode Architecture](docs/proxy-mode.md)
|
|
* [Sandboxing Details](docs/sandbox.md)
|
|
|
|
## Support
|
|
|
|
If PMG saved you from a bad package, [star this repo](https://github.com/safedep/pmg) — it helps others find it.
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to build and test PMG locally.
|
|
|
|
## Telemetry
|
|
|
|
PMG collects anonymous usage data to improve project stability and reliability.
|
|
To disable, either:
|
|
- Set `disable_telemetry: true` in your PMG config file, or
|
|
- Export `PMG_DISABLE_TELEMETRY=true`.
|