{"_id":"@dendronhq/safe-npm","name":"@dendronhq/safe-npm","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dendronhq/safe-npm","version":"0.1.0","description":"A security-focused npm installer that protects your projects from newly compromised packages","type":"module","bin":{"safe-npm":"dist/cli.js"},"scripts":{"build":"tsc","start":"node dist/cli.js","test":"tsc && vitest run","prepublishOnly":"npm run build && npm test"},"keywords":["npm","security","supply-chain","package-manager","dependency","install","safe","audit"],"author":"","license":"ISC","dependencies":{"axios":"^1.7.0","commander":"^12.0.0","semver":"^7.6.0"},"devDependencies":{"@types/node":"^24.10.1","@types/semver":"^7.7.1","typescript":"^5.5.0","vitest":"^1.6.1"},"_id":"@dendronhq/safe-npm@0.1.0","gitHead":"336724b45c6649d49401dfe7fcb14c0d22e064d2","_nodeVersion":"22.7.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-vR3y0kdR26lKdVW2oK/IQssIlLVqHKfio+fX3OLXEjNfZ0DT59xp5kw9NKMSiW6z65ozgEKS4cmPfNNdNlfJdA==","shasum":"60b4dd2a31199f4fa32d2a52fa9731448ffbc673","tarball":"https://registry.npmjs.org/@dendronhq/safe-npm/-/safe-npm-0.1.0.tgz","fileCount":5,"unpackedSize":22577,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIC2auQpyGNymgUVLK4IJSViit5xLaEAnBWSNJGNxdulIAiAuB3g6RYpobAZgIXU4vtv/5A/U+qk0JRHWc06Mec40lw=="}]},"_npmUser":{"name":"kevins8","email":"kevinslin8@gmail.com"},"directories":{},"maintainers":[{"name":"kevins8","email":"kevinslin8@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/safe-npm_0.1.0_1763935076192_0.06377296927438292"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-23T21:57:56.132Z","0.1.0":"2025-11-23T21:57:56.400Z","modified":"2025-11-23T21:57:56.637Z"},"maintainers":[{"name":"kevins8","email":"kevinslin8@gmail.com"}],"description":"A security-focused npm installer that protects your projects from newly compromised packages","keywords":["npm","security","supply-chain","package-manager","dependency","install","safe","audit"],"license":"ISC","readme":"# safe-npm\n\nA security-focused npm installer that protects your projects from newly compromised packages.\n\n## Why does this exist?\n\nSupply chain attacks on npm packages are a growing threat. Attackers sometimes compromise legitimate packages by:\n- Stealing maintainer credentials\n- Publishing malicious updates to popular packages\n- Taking over abandoned packages\n\nThese attacks often happen suddenly—a package that was safe yesterday might be compromised today. **safe-npm** protects you by only installing package versions that have been publicly available for a minimum amount of time (90 days by default). This gives the security community time to discover and report malicious releases before they reach your project.\n\n## How it works\n\nWhen you run `safe-npm install`, it:\n\n1. Reads your dependencies from `package.json` or command-line arguments\n2. Queries the npm registry to find all available versions\n3. Filters out versions published more recently than your minimum age threshold\n4. Selects the newest version that meets both your semver requirements AND age requirements\n5. Installs the safe versions using npm\n\nFor example, if you specify `react@^18` and a malicious `react@18.5.0` was published yesterday, safe-npm will install the latest version that's at least 90 days old instead.\n\n## Installation\n\n### Install from npm (recommended)\n\n```bash\n# Install globally\nnpm install -g @kevins8/safe-npm\n\n# Now you can use it anywhere\nsafe-npm install\n```\n\n### Build from source\n\n```bash\n# Clone and build\ngit clone <repository-url>\ncd safe-npm\nnpm install\nnpm run build\n\n# Link the binary globally\nnpm link\n```\n\n## Basic usage\n\n### Install dependencies from package.json\n\n```bash\n# Use the minimum age of 90 days (default)\nsafe-npm install\n\n# Or specify your own minimum age\nsafe-npm install --min-age-days 120\n```\n\n### Install specific packages\n\n```bash\n# Install packages directly with version constraints\nsafe-npm install react@^18 lodash@^4.17.0\n\n# These will be filtered to only use versions at least 90 days old\nsafe-npm install express --min-age-days 60\n```\n\n### Dry run to see what would be installed\n\n```bash\n# Preview which versions would be installed without actually installing\nsafe-npm install --dry-run\n```\n\n## Configuration options\n\n### `--min-age-days <n>`\n**Default:** `90`\n\nThe minimum number of days a package version must have been published before it can be installed.\n\n**Example:** `--min-age-days 120` requires packages to be at least 4 months old.\n\n**When to adjust:**\n- Increase for maximum security (e.g., 180 days for critical production systems)\n- Decrease if you need newer features and accept slightly more risk (e.g., 30 days)\n\n### `--ignore <pkg1,pkg2>`\n\nA comma-separated list of packages that bypass the age requirement. These packages will still respect semver ranges but ignore the minimum age.\n\n**Example:** `--ignore typescript,@types/node`\n\n**When to use:**\n- Fast-moving packages you trust (like TypeScript or build tools)\n- Internal packages from your organization\n- Packages where you need the latest features urgently\n\n### `--strict`\n\nExit with an error if ANY dependency cannot be resolved to a version meeting the age requirement.\n\n**Example:** `safe-npm install --strict`\n\n**When to use:**\n- CI/CD pipelines where you want builds to fail rather than skip problematic packages\n- Production deployments where you need certainty\n\n### `--dev` / `--prod-only`\n\nControl which dependencies from `package.json` are processed.\n\n**Examples:**\n- `safe-npm install --dev` - Only install devDependencies\n- `safe-npm install --prod-only` - Only install production dependencies\n\n**When to use:**\n- Installing development tools with stricter requirements\n- Production builds where you want different age policies for dev vs prod dependencies\n\n### `--strategy <direct|overrides>`\n**Default:** `direct`\n\nHow safe-npm installs the resolved versions:\n\n**`direct`** - Directly installs the resolved versions using `npm install package@version`\n- Simple and straightforward\n- Good for one-time installs or scripts\n\n**`overrides`** - Writes resolved versions to `package.json` overrides field, then runs `npm install`\n- Enforces versions across your entire dependency tree (including transitive dependencies)\n- **Note:** This feature is currently disabled as it doesn't work correctly yet\n\n### `--registry <url>`\n**Default:** `https://registry.npmjs.org`\n\nSpecify an alternate npm registry.\n\n**Example:** `--registry https://registry.company.com`\n\n**When to use:**\n- Private npm registries\n- Mirrors or caches\n\n### `--dry-run`\n\nShow what would be installed without making any changes.\n\n**Example:** `safe-npm install --dry-run`\n\n**When to use:**\n- Testing your configuration\n- Understanding what versions are available\n- Before making changes to production systems\n\n## Common workflows\n\n### Secure a new project\n\n```bash\n# Create a new project\nmkdir my-project && cd my-project\nnpm init -y\n\n# Install dependencies safely\nsafe-npm install express@^4 lodash\n\n# This creates package-lock.json with versions at least 90 days old\n```\n\n### Audit an existing project\n\n```bash\n# Check what versions would be installed with age requirements\nsafe-npm install --dry-run\n\n# If you're happy, install them\nsafe-npm install\n```\n\n### CI/CD integration\n\n```bash\n# In your CI pipeline, fail the build if any package can't meet age requirements\nsafe-npm install --strict --min-age-days 120\n\n# Or allow newer packages for dev dependencies only\nsafe-npm install --prod-only --strict\n```\n\n### Emergency updates\n\n```bash\n# Need to urgently update a specific package? Add it to ignore list\nsafe-npm install --ignore package-with-critical-fix\n```\n\n## Testing\n\nThe project includes a test suite that you can run:\n\n```bash\nnpm test\n```\n\nFor automated testing, you can mock registry responses using fixtures:\n\n```bash\nexport SAFE_NPM_FIXTURES=/path/to/fixtures.json\nsafe-npm install\n```\n\nThe fixtures file should contain JSON that mirrors npm registry responses for each package.\n\n## How this protects you\n\n**Real-world scenario:**\n\n1. A popular package `popular-lib` is maintained by a trusted developer\n2. Attacker compromises the maintainer's npm credentials\n3. Attacker publishes `popular-lib@5.0.0` with malware\n4. Projects using `^5.0.0` would immediately install the malicious version\n5. With safe-npm, you'd keep using `4.9.0` (the latest version from 90+ days ago)\n6. Security researchers discover the compromise and report it\n7. The malicious version is unpublished\n8. You never installed the compromised version\n\n## Limitations\n\n- Won't protect against packages that were malicious from the start\n- Delays access to legitimate new features and bug fixes\n- Requires trust that older versions don't have undiscovered vulnerabilities\n- Age-based filtering is a heuristic, not a guarantee\n\n## Philosophy\n\nSecurity is about trade-offs. safe-npm trades bleeding-edge updates for protection against sudden supply chain compromises. It's one layer in a defense-in-depth strategy that should also include:\n\n- Regular security audits (`npm audit`)\n- Dependency review before adding new packages\n- Monitoring for security advisories\n- Using lock files to ensure reproducible builds\n- Running in sandboxed or containerized environments\n\n## Requirements\n\n- Node.js 18 or higher\n- npm (for the underlying installation)\n\n## License\n\nISC\n","readmeFilename":"README.md","_rev":"1-d8729e63b3bf8171d3e888d9b89e7220"}