npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

git-tag-guardian

v1.0.0

Published

Zero-dependency supply chain defense for Node.js/Bun — detects git tag rewrite attacks, postinstall backdoors, SHA drift, tarball tampering and unpinned GitHub Actions

Readme

git-tag-guardian

Zero-dependency supply chain defense for Node.js and Bun projects.

Detects and blocks Git Tag Rewrite attacks, postinstall backdoors, SHA drift in lockfiles, tarball tampering, and unpinned GitHub Actions — before they compromise your CI/CD or production.

Built by CanisterWorm / TeamPCP as a practical countermeasure to real-world tag rewrite exploitation techniques.


The Problem

Git tags are mutable. Anyone with push access to a repository can silently repoint a tag to a completely different commit — including one from a fork that contains a backdoor. npm, GitHub Actions, and Dockerfiles that reference dependencies by tag will then pull the malicious code without any warning.

Attack chain:

1. Attacker forks your dependency
2. Adds malicious code in the fork (postinstall exfiltration, modified source, etc.)
3. Pushes to fork — commit lands in shared GitHub Object Store
4. Rewrites the tag in upstream: PATCH /git/refs/tags/v1.0.0 { sha: "malicious", force: true }
5. GitHub regenerates .tar.gz automatically
6. Next `npm install` pulls compromised code
7. postinstall runs silently — steals env vars, SSH keys, tokens

This tool detects every stage of that chain.


Install

# As a dev dependency
npm install --save-dev git-tag-guardian

# Or run directly
npx git-tag-guardian audit

No external dependencies. Works on Node.js >= 18 and Bun.


Quick Start

# 1. Full audit of current project
npx git-tag-guardian audit

# 2. Create a baseline (records current SHA hashes)
npx git-tag-guardian baseline

# 3. Install git hooks (pre-commit + post-merge)
npx git-tag-guardian hooks-install

# 4. Run in CI (exits 1 on critical/high findings)
npx git-tag-guardian audit --ci

5 Security Checks

1. SHA Pinning

Detects git dependencies in package.json that reference tags or branches instead of full 40-character SHA hashes. Tags can be rewritten; SHA hashes cannot.

[HIGH] Dependency "logger" references tag "v1.0.0" instead of SHA
       fix: Replace with full SHA commit hash

2. Postinstall Hook Detection

Scans every package in node_modules/ for lifecycle scripts (preinstall, install, postinstall, prepare, etc.) and analyzes their content for 15+ suspicious patterns:

| Pattern | Risk | |---------|------| | curl / wget / fetch() to external URLs | Data exfiltration | | process.env access | Credential theft | | .ssh/ access | SSH key theft | | .bashrc / .zshrc modification | Persistent backdoor | | .npmrc modification | Registry hijacking | | child_process / exec / eval | Arbitrary code execution | | Buffer.from(..., 'base64') | Obfuscation | | os.userInfo() / os.hostname() | Reconnaissance | | dns.resolve / dns.lookup | DNS exfiltration |

Packages with 3+ suspicious patterns are flagged as CRITICAL.

3. Tag Integrity (GitHub API)

Queries the GitHub API to verify that tag SHA matches the baseline. Detects tag rewrite attacks in real-time. Also checks whether the commit belongs to the default branch or is a fork commit (strong indicator of attack).

[CRIT] TAG REWRITE DETECTED: owner/repo#v1.0.0 SHA changed!
       baseline SHA: 1fadba8...
       remote SHA:   16e4324... (from fork!)

Requires GITHUB_TOKEN environment variable.

4. Tarball Integrity

Downloads .tar.gz archives from GitHub for tag-based dependencies and compares SHA256 hashes against the baseline. GitHub regenerates tarballs dynamically after tag rewrite — same URL, different content.

[CRIT] TARBALL CHANGED: "logger" .tar.gz hash changed!
       baseline: 475308ac...
       current:  4204c3e4...

5. GitHub Actions Pinning

Scans .github/workflows/*.yml for uses: directives that reference actions by tag instead of SHA. An action tag rewrite gives attackers access to GITHUB_TOKEN, all secrets, and build artifacts.

[HIGH] Action "third-party/action@v2" uses tag instead of SHA!
       fix: uses: third-party/action@<40-char-sha> # v2

Baseline System

The baseline records known-good SHA hashes for dependencies, tags, and tarballs. Subsequent audits compare current state against the baseline to detect drift.

# Create initial baseline
npx git-tag-guardian baseline

# Commit it
git add .guardian-baseline.json
git commit -m "Add supply chain baseline"

The baseline file (.guardian-baseline.json) should be committed to your repository so every developer and CI runner uses the same reference.


GitHub Actions Workflow

A ready-to-use CI workflow is included at .github/workflows/supply-chain-guard.yml:

  • Runs on every PR that touches package.json / package-lock.json
  • Runs on push to main / master
  • Scheduled daily cron for tag rewrite detection between commits
  • Posts findings as PR comments on failure
  • All actions in the workflow itself are SHA-pinned
# Key: install with --ignore-scripts to prevent postinstall execution
- run: npm ci --ignore-scripts
- run: npx git-tag-guardian audit --ci

Git Hooks

npx git-tag-guardian hooks-install

Installs two hooks:

  • pre-commit — blocks commits that introduce SHA drift or new lifecycle hooks
  • post-merge — automatically checks dependencies after git pull

Configuration

Create .guardian.yml in your project root (optional — sensible defaults are used otherwise):

checks:
  shaPinning: true
  postinstallHooks: true
  tagIntegrity: true        # requires GITHUB_TOKEN
  tarballIntegrity: true
  actionsPinning: true

# Packages allowed to have lifecycle scripts
allowedLifecyclePackages:
  - electron
  - sharp
  - better-sqlite3

# Actions owners trusted (severity: low instead of high)
trustedActions:
  - actions/*

# Baseline file name
baselineFile: .guardian-baseline.json

# Minimum severity to fail CI
failOnSeverity: high

CLI Reference

COMMANDS:
  audit           Full project audit (all 5 checks)
  baseline        Create/update SHA baseline
  verify          Quick check (SHA drift + postinstall only)
  hooks-install   Install git hooks (pre-commit, post-merge)
  help            Show help

FLAGS:
  --ci            CI mode (exit 1 on critical/high findings)
  --cwd <path>    Project root (default: cwd)
  --token <tok>   GitHub PAT for API checks (or GITHUB_TOKEN env)
  --output <file> Save report as JSON
  --no-color      Disable colors

Integration with AI Coding Agents

This project ships companion skills for Claude Code and OpenCode that automatically run supply chain checks when the agent installs npm packages:

These skills hook into the agent's npm install / bun install workflow and block installation if critical findings are detected.


How It Works (Technical)

Git Tag Rewrite Attack

Upstream repo:  owner/logger
  refs/tags/v1.0.0 → commit abc123 (clean)

Attacker fork:  attacker/logger
  branch: malicious → commit xyz789 (backdoor)

API call (with push access):
  PATCH /repos/owner/logger/git/refs/tags/v1.0.0
  { "sha": "xyz789", "force": true }

Result:
  refs/tags/v1.0.0 → commit xyz789 (backdoor!)
  .tar.gz regenerated with malicious content
  npm install pulls backdoor automatically

Why SHA Pinning Stops It

SHA-256 commit hashes are cryptographically unique. A rewritten tag points to a different SHA — but if your package-lock.json or baseline records the original SHA, the drift is immediately detectable.


Severity Levels

| Severity | Meaning | CI Impact | |----------|---------|-----------| | critical | Active attack indicator (SHA drift, tag rewrite, dangerous hooks) | Fail | | high | Missing protection (tag-based deps, unpinned actions) | Fail | | medium | Informational risk (short SHA, missing baseline) | Pass | | low | Best practice suggestion | Pass | | info | Informational only | Pass |


License

MIT


CanisterWorm / TeamPCP — Practical security tooling for the Node.js ecosystem.