agentsclimarketplace

Supply chain security

Skill vibeeval/vibecosystem/skills/supply-chain-security

AI software team for Claude Code - 138 agents, 295 skills, 73 hooks. Self-learning, multi-agent swarm, autonomous skill evolution.

Install
npx -y skills add vibeeval/vibecosystem --skill supply-chain-security

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Typosquatting detection, install script analysis, dependency confusion prevention, and phantom dependency detection for npm/pip.

SKILL.md

8.9 KB, as published. Nobody here has run it

Supply Chain Security

Patterns for auditing third-party dependencies before they own your production environment.

Typosquatting Detection

Common substitution patterns attackers use against popular packages:

# Levenshtein distance check against known-good package list
def levenshtein(a: str, b: str) -> int:
    if len(a) < len(b):
        return levenshtein(b, a)
    if not b:
        return len(a)
    prev = list(range(len(b) + 1))
    for i, ca in enumerate(a):
        curr = [i + 1]
        for j, cb in enumerate(b):
            curr.append(min(prev[j + 1] + 1, curr[j] + 1, prev[j] + (ca != cb)))
        prev = curr
    return prev[-1]

POPULAR_PACKAGES = ['express', 'lodash', 'react', 'axios', 'moment', 'chalk']

def is_typosquat(pkg: str, threshold: int = 2) -> list[str]:
    return [p for p in POPULAR_PACKAGES if 0 < levenshtein(pkg, p) <= threshold]

# Examples of known typosquats
typosquats = {
    'lodahs': 'lodash',       # character swap
    'expres': 'express',      # missing char
    'reakt': 'react',         # phonetic substitution
    'axois': 'axios',         # transposition
    'momnet': 'moment',       # transposition
}

Common substitution patterns to check manually:

  • Character transposition: lodashlodahs
  • Missing character: expressexpres
  • Extra character: chalkcchalk
  • Hyphen/underscore swap: my-libmy_lib
  • Homoglyph: rn instead of m in package name

Install Script Audit

# List all packages with install scripts (npm)
npm query ":root > *" | \
  node -e "const d=require('/dev/stdin');
    Object.entries(d.dependencies||{}).forEach(([k,v])=>{
      const pkg = require(\`./node_modules/\${k}/package.json\`);
      if(pkg.scripts?.preinstall||pkg.scripts?.postinstall||pkg.scripts?.install)
        console.log(k, Object.keys(pkg.scripts))
    })"

# Safer: use npm pack --dry-run to see what a package would install
npm pack lodash --dry-run

# Check a specific package's install scripts before installing
npm show <package> scripts
// Automated install script audit
import { execSync } from 'child_process'
import fs from 'fs'
import path from 'path'

function auditInstallScripts(nodeModulesDir: string): void {
  const packages = fs.readdirSync(nodeModulesDir)

  for (const pkg of packages) {
    const pkgJsonPath = path.join(nodeModulesDir, pkg, 'package.json')
    if (!fs.existsSync(pkgJsonPath)) continue

    const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'))
    const scripts = pkgJson.scripts ?? {}
    const suspicious = ['preinstall', 'postinstall', 'install']
      .filter(s => s in scripts)

    if (suspicious.length > 0) {
      console.warn(`[WARN] ${pkg} has install scripts: ${suspicious.join(', ')}`)
      console.warn(`       ${scripts[suspicious[0]]}`)
    }
  }
}

auditInstallScripts('./node_modules')

Dependency Confusion Risk Assessment

# Check if your internal package names exist on the public registry
# If they do AND the public version is newer, npm may pull the public one

INTERNAL_PACKAGES=("@mycompany/auth" "@mycompany/utils" "internal-logger")

for pkg in "${INTERNAL_PACKAGES[@]}"; do
  result=$(npm show "$pkg" version 2>/dev/null)
  if [ -n "$result" ]; then
    echo "RISK: $pkg exists on public registry at version $result"
  else
    echo "OK:   $pkg not on public registry"
  fi
done

Prevention in .npmrc:

# Force scoped packages to your private registry
@mycompany:registry=https://npm.mycompany.com
@internal:registry=https://npm.mycompany.com

# Block public fallback for scoped packages
//npm.mycompany.com/:always-auth=true

Phantom Dependency Detection

# Find imports/requires that aren't in package.json
# Node.js (using depcheck)
npx depcheck --ignores="@types/*" .

# Python (using pipreqs)
pip install pipreqs
pipreqs . --print | sort > required.txt
pip freeze | sort > installed.txt
diff required.txt installed.txt
// Custom phantom dep detector for TypeScript
import { execSync } from 'child_process'
import fs from 'fs'

function detectPhantomDeps(srcDir: string): void {
  const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'))
  const declared = new Set([
    ...Object.keys(pkgJson.dependencies ?? {}),
    ...Object.keys(pkgJson.devDependencies ?? {}),
  ])

  // Extract all import/require statements
  const imports = execSync(
    `rg --no-heading -oh "from ['\"]([^./][^'\"]+)['\"]" ${srcDir} | sed "s/from ['\"]//;s/['\"]//;s/\\/.*//"`
  ).toString().split('\n').filter(Boolean)

  const unique = new Set(imports)
  for (const imp of unique) {
    const root = imp.startsWith('@') ? imp.split('/').slice(0, 2).join('/') : imp.split('/')[0]
    if (!declared.has(root)) {
      console.warn(`[PHANTOM] "${root}" is imported but not in package.json`)
    }
  }
}

Lock File Integrity Verification

# Verify package-lock.json integrity (npm)
npm ci --dry-run

# Detect if lock file is out of sync with package.json
npm install --package-lock-only
git diff --exit-code package-lock.json

# pip: verify requirements are pinned with hashes
pip install --require-hashes -r requirements.txt

# Generate hash-pinned requirements
pip-compile --generate-hashes requirements.in -o requirements.txt

npm audit / pip-audit Integration

# npm - break build on high severity
npm audit --audit-level=high

# pip-audit
pip install pip-audit
pip-audit --requirement requirements.txt --fail-on CRITICAL,HIGH

# GitHub Actions integration
- name: Security audit
  run: |
    npm audit --audit-level=moderate
    npx better-npm-audit audit --level moderate

SBOM Generation

# CycloneDX for Node.js
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --output-format JSON --output-file sbom.json

# CycloneDX for Python
pip install cyclonedx-bom
cyclonedx-bom -r -o sbom.xml

# SPDX via syft
syft . -o spdx-json > sbom.spdx.json

Known Malicious Package Indicators

Red flags when reviewing a new dependency:

- Install scripts that curl | bash external URLs
- Package published < 48 hours ago with thousands of weekly downloads
- Zero issues/stars on GitHub but high download count
- package.json "main" points to an obfuscated file
- Dependencies on packages with random hex names
- Author email is a free provider with a new account
- Version bump from 1.x to 99.x (dependency confusion attack)

Dependency Pinning Strategy

// package.json: exact pinning for production deps
{
  "dependencies": {
    "express": "4.18.2",      // exact - no caret/tilde
    "lodash": "4.17.21"
  },
  "devDependencies": {
    "typescript": "^5.3.0"   // range OK for dev tools
  }
}
# Convert all ranges to exact versions
npm shrinkwrap
# or use: npm-shrinkwrap.json over package-lock.json for published packages

# Renovate bot for automated safe updates with PR-per-dep
# renovate.json
{
  "extends": ["config:base"],
  "automerge": false,
  "reviewers": ["security-team"]
}

Dependency Risk Scoring

Score each dependency on a 0-100 risk scale before adoption:

SignalLow Risk (0-2)Medium Risk (3-5)High Risk (6-10)
Age> 3 years1-3 years< 1 year
Maintainers3+ active1-2 active1 inactive
Downloads> 1M/week100K-1M/week< 100K/week
GitHub stars> 5K500-5K< 500
Last commit< 3 months3-12 months> 12 months
Open issues< 5050-200> 200 unresolved
Install scriptsNonepostinstall (build)preinstall + network
Dependencies< 55-20> 20 transitive
CVE history0 unfixedFixed promptlyUnfixed > 30 days
LicenseMIT/Apache/BSDLGPL/MPLGPL/AGPL/Unknown

Risk Assessment Template

Package: <name>@<version>
Purpose: <why we need it>
Alternatives: <what else we considered>

Signals:
  Age: X years (score: N)
  Maintainers: X active (score: N)
  Downloads: X/week (score: N)
  Last commit: X days ago (score: N)
  Dependencies: X transitive (score: N)
  CVEs: X unfixed (score: N)

Total Risk Score: XX/100
Decision: [ADOPT | REVIEW | REJECT]
Reviewed by: <name>
Date: <date>

Automated Risk Check

# npm: check package metadata
npm show <package> time modified maintainers repository

# Check download stats
curl -s "https://api.npmjs.org/downloads/point/last-week/<package>" | jq .downloads

# Check for known vulnerabilities
npm audit --json | jq '.vulnerabilities["<package>"]'

# Python: check PyPI metadata
pip show <package>
pip-audit -r requirements.txt --format json

Rule: Never npm install <unknown-package> in production without running npm audit, checking install scripts, and verifying the package name against known typosquats.

Dependency risk scoring adapted from Trail of Bits supply-chain-risk-auditor plugin.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.