lockcheck-muin
v1.0.0
Published
Verify lockfile integrity. Detect suspicious registries, duplicate versions, missing hashes.
Maintainers
Readme
lockcheck
Verify lockfile integrity. Detect suspicious registries, duplicate versions, missing hashes.
Why?
Supply chain attacks are real. Lockfiles can contain packages from unexpected registries, missing integrity hashes, or other red flags that automated CI should catch before they hit production.
lockcheck does one thing well: scan your package-lock.json and warn you about potential security issues.
Installation
npm install -g lockcheckOr run without installing:
npx lockcheckUsage
# Check current directory
lockcheck
# Check specific file
lockcheck ./path/to/package-lock.json
# Get JSON output
lockcheck --json
# Treat warnings as errors (for CI)
lockcheck --strictWhat it checks
- Suspicious registries - Packages not from registry.npmjs.org or registry.yarnpkg.com
- Missing integrity hashes - Packages without SHA verification
- Duplicate versions - Same package with multiple versions (bloats node_modules)
Examples
Example 1: Clean Project - All Good ✅
Scenario: Well-maintained project with standard dependencies.
$ cd my-clean-project
$ lockcheck
🔍 Scanning package-lock.json...
✅ Lockfile looks good!
📊 Summary:
- Total packages: 342
- Registries: 1 (registry.npmjs.org)
- All integrity hashes present: ✓
- No duplicate versions found: ✓
Exit code: 0Result: Safe to deploy!
Example 2: Suspicious Registry Detected 🚨
Scenario: A compromised dependency or typosquatting attempt.
$ lockcheck
🔍 Scanning package-lock.json...
⚠️ SECURITY WARNINGS:
🚨 Suspicious Registry:
- [email protected]
Expected: https://registry.npmjs.org
Found: https://malicious-registry.com/evil-package/-/evil-package-1.0.0.tgz
⚠️ This package is NOT from the official npm registry!
Risk: Supply chain attack, malware injection
🔍 Recommended Action:
1. Check if this is a private/corporate registry (expected behavior)
2. If not, REMOVE this package immediately
3. Run `npm audit` and scan for malware
4. Notify your security team
Exit code: 1Action: Investigate and remove the suspicious package.
Example 3: Missing Integrity Hashes
Scenario: Old lockfile or manually edited file missing SHA checksums.
$ lockcheck
🔍 Scanning package-lock.json...
⚠️ MISSING INTEGRITY HASHES:
❌ [email protected] - No integrity hash found
❌ [email protected] - No integrity hash found
❌ [email protected] - No integrity hash found
📊 Summary:
- Total packages: 89
- Missing integrity: 3
⚠️ Without integrity hashes, npm cannot verify package contents!
This allows for man-in-the-middle attacks or corrupted packages.
🔧 Fix:
rm -rf node_modules package-lock.json
npm install
Exit code: 1Example 4: Duplicate Versions Bloating node_modules
Scenario: Different versions of the same package installed, wasting space.
$ lockcheck
🔍 Scanning package-lock.json...
⚠️ DUPLICATE VERSIONS:
📦 lodash found in 3 different versions:
- 4.17.20 (used by: webpack, babel-core)
- 4.17.21 (used by: express, mocha)
- 3.10.1 (used by: legacy-lib)
📦 moment found in 2 different versions:
- 2.29.1 (used by: react-datepicker)
- 2.30.0 (used by: chart.js)
📊 Impact:
- Extra disk space: ~450 KB
- Potential bugs from version mismatch
💡 Fix:
npm dedupe # Attempts to flatten dependency tree
# Or update dependencies to use consistent versions
Exit code: 0 (warning only)Example 5: CI Enforcement with --strict Mode
Scenario: Block any lockfile issues in your CI pipeline.
$ lockcheck --strict
🔍 Scanning package-lock.json...
⚠️ Warnings found (treated as errors in --strict mode):
- Package lodash has 2 different versions: 4.17.20, 4.17.21
- Package moment has 2 different versions: 2.29.1, 2.30.0
❌ FAILED: 2 warnings in --strict mode
Exit code: 1 ← Build failsGitHub Actions Example:
- name: Check lockfile
run: npx lockcheck --strictResult: PR is blocked until duplicates are resolved.
Example 6: JSON Output for Automation
Scenario: Integrate lockcheck results into your security dashboard.
$ lockcheck --json > lockfile-report.jsonOutput (lockfile-report.json):
{
"passed": false,
"errors": [
{
"type": "suspicious_registry",
"package": "evil-package",
"version": "1.0.0",
"registry": "https://malicious-registry.com",
"expected": "https://registry.npmjs.org"
}
],
"warnings": [
{
"type": "duplicate_version",
"package": "lodash",
"versions": ["4.17.20", "4.17.21"]
}
],
"summary": {
"totalPackages": 342,
"registries": [
"https://registry.npmjs.org",
"https://malicious-registry.com"
],
"missingIntegrity": 0,
"duplicates": 1
}
}Use case: Parse JSON, send alerts to Slack/PagerDuty if passed: false.
CI Integration
Add to your GitHub Actions workflow:
- name: Check lockfile integrity
run: npx lockcheck --strictExit code is 0 if passed, 1 if errors found. Perfect for blocking bad merges.
API
Use programmatically:
import { checkLockfileFromPath } from 'lockcheck';
const result = checkLockfileFromPath('./package-lock.json', {
strict: true,
allowedRegistries: ['https://registry.npmjs.org']
});
if (!result.passed) {
console.error('Issues found:', result.errors);
}Options
--json- Output results as JSON--strict- Treat warnings as errors (fails with exit code 1)--help- Show help
Real-World Examples
1. CI/CD Security Gate
GitHub Actions:
# .github/workflows/security.yml
name: Security Checks
on:
push:
branches: [main]
pull_request:
paths:
- 'package-lock.json'
- 'yarn.lock'
jobs:
lockfile-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Verify lockfile integrity
run: npx lockcheck --strict
- name: Block merge on suspicious packages
if: failure()
run: |
echo "❌ Lockfile contains security issues"
echo "Review registry sources and missing hashes"
exit 1GitLab CI:
# .gitlab-ci.yml
lockfile-audit:
stage: security
script:
- npx lockcheck --strict
only:
changes:
- package-lock.json
allow_failure: false2. Pre-commit Hook
Catch lockfile issues before they're committed:
#!/bin/bash
# .git/hooks/pre-commit
if git diff --cached --name-only | grep -q "package-lock.json"; then
echo "🔍 Checking lockfile integrity..."
npx lockcheck --strict
if [ $? -ne 0 ]; then
echo "❌ Lockfile has issues. Fix before committing."
exit 1
fi
echo "✅ Lockfile is clean"
fiWith husky:
{
"husky": {
"hooks": {
"pre-commit": "lockcheck --strict"
}
}
}3. Monorepo Scanning
Check all lockfiles in a monorepo:
# Find and check all lockfiles
find . -name "package-lock.json" -not -path "*/node_modules/*" | while read lockfile; do
echo "Checking $lockfile"
lockcheck "$lockfile" --strict
done
# Or with parallel processing
find . -name "package-lock.json" -not -path "*/node_modules/*" | \
parallel lockcheck {} --strict4. Custom Registry Whitelist
For organizations using private registries:
# Allow specific registries (feature request - example config)
# lockcheck.config.json
{
"allowedRegistries": [
"https://registry.npmjs.org",
"https://npm.internal.company.com",
"https://artifacts.company.io"
],
"strict": true
}
# Then run
lockcheck --config lockcheck.config.json5. Automated Dependency Updates
Combine with Dependabot or Renovate:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
# After Dependabot creates PR, lockcheck runs automaticallyGitHub Action to verify Dependabot PRs:
name: Verify Dependency Updates
on:
pull_request:
branches: [main]
jobs:
check-deps:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Verify lockfile
run: npx lockcheck --strict
- name: Auto-merge if safe
if: success()
run: gh pr merge --auto --squash ${{ github.event.pull_request.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}6. JSON Output for Reporting
Generate security reports:
# Generate JSON report
lockcheck --json > lockfile-report.json
# Parse with jq
lockcheck --json | jq '.errors'
# Count issues
lockcheck --json | jq '.errors | length'
# Alert if issues found
lockcheck --json | jq -e '.passed == false' && \
curl -X POST https://alerts.company.com/webhook \
-d "Lockfile security issues detected"7. Periodic Security Audits
Weekly lockfile health checks:
# crontab
0 9 * * 1 cd /path/to/project && lockcheck --json > reports/lockcheck-$(date +\%Y\%m\%d).json
# GitHub Actions scheduled scan
# .github/workflows/weekly-audit.yml
name: Weekly Security Audit
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9 AM
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run lockfile check
run: lockcheck --json > lockcheck-report.json
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: lockfile-audit
path: lockcheck-report.json
- name: Notify on Slack if issues
if: failure()
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-d '{"text":"⚠️ Weekly lockfile audit found issues"}'8. Emergency Response
When a supply chain attack is detected:
# Quick scan across all projects
for repo in ~/projects/*/; do
if [ -f "$repo/package-lock.json" ]; then
echo "Scanning $repo"
lockcheck "$repo/package-lock.json" --strict || echo "⚠️ Issue in $repo"
fi
done
# Generate org-wide report
for repo in ~/projects/*/; do
if [ -f "$repo/package-lock.json" ]; then
echo "$repo" >> org-report.txt
lockcheck "$repo/package-lock.json" --json >> org-report.txt
fi
doneContributing
PRs welcome. Keep it simple.
- Fork the repo
- Create a feature branch
- Add tests for new features
- Run
npm test - Submit PR
License
MIT
