{"_id":"@azlabs/depguard","_rev":"3-f187ffde97a762090cf7de4f80fe7e78","name":"@azlabs/depguard","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@azlabs/depguard","version":"0.1.0","keywords":["npm","security","supply-chain","dependencies","audit","cli"],"license":"MIT","_id":"@azlabs/depguard@0.1.0","maintainers":[{"name":"matheusaz","email":"matheuspavaneli@proton.me"}],"bin":{"depguard":"dist/cli.js"},"dist":{"shasum":"342fecb7fc2c102da7056dd9542ba87ec7319b66","tarball":"https://registry.npmjs.org/@azlabs/depguard/-/depguard-0.1.0.tgz","fileCount":5,"integrity":"sha512-vna2p1v68p/DiIZNkUfV4sKvAK4jeZMqN+tbpqV8nESr/J0yNMUXIEfR4AkOH9ceNO0RqWobLW0EVB8orBzY4A==","signatures":[{"sig":"MEUCIQDo2HyVqIBnYfzrr/qgq5LvhGiNxrhWpn7LpZoiJyBnagIge/9YIlwpN7fAe50mBT9+zqThUopp48AsliV5HpAHadA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107787},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"36945ba2074678ff0effc030bc463de889c1eacb","scripts":{"dev":"tsx src/cli.ts","test":"vitest run","build":"tsup","eval:metrics":"tsx scripts/eval-metrics.mts","prepublishOnly":"npm run build","generate:popular":"tsx scripts/generate-popular-packages.mts"},"_npmUser":{"name":"matheusaz","email":"matheuspavaneli@proton.me"},"_npmVersion":"10.8.2","description":"CLI for preventive npm dependency risk scoring: registry metadata, lifecycle scripts, OSV, typosquatting heuristics","directories":{},"_nodeVersion":"20.20.0","dependencies":{"cac":"^6.7.14","chalk":"^5.4.1","pacote":"^21.0.0","semver":"^7.7.1","p-limit":"^6.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.7.3","tsx":"^4.19.3","tsup":"^8.4.0","vitest":"^3.0.9","typescript":"^5.8.2","@types/node":"^22.13.10","@types/semver":"^7.5.8"},"_npmOperationalInternal":{"tmp":"tmp/depguard_0.1.0_1774152201156_0.25689477777502456","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@azlabs/depguard","version":"0.2.0","keywords":["npm","security","supply-chain","dependencies","audit","cli"],"license":"MIT","_id":"@azlabs/depguard@0.2.0","maintainers":[{"name":"matheusaz","email":"matheuspavaneli@proton.me"}],"bin":{"depguard":"dist/cli.js"},"dist":{"shasum":"ce4a13ccdc888f468e49aeb70ac860906340491d","tarball":"https://registry.npmjs.org/@azlabs/depguard/-/depguard-0.2.0.tgz","fileCount":6,"integrity":"sha512-LrY+y4jW4rqAKsplWKqMm/ExdYV15CHjlZ20vXud7MP25xsZkuiHoIoNxt7VSjOUO/iGCaJ2lVJ+Na2gI0gfXA==","signatures":[{"sig":"MEUCIGluwUAkSLvgDITu6IRsuaWanKp0zB5PNkwPcX1NUHXKAiEA+6wP+pAEuHMlIYFMAWLxsb6VGezbimkw4TS+dcL2or8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":123847},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"7a5bde7230779b3719fbb4731d9837939cab9f8a","scripts":{"dev":"tsx src/cli.ts","test":"vitest run","build":"tsup","eval:metrics":"tsx scripts/eval-metrics.mts","prepublishOnly":"npm run build","generate:popular":"tsx scripts/generate-popular-packages.mts"},"_npmUser":{"name":"matheusaz","email":"matheuspavaneli@proton.me"},"_npmVersion":"10.8.2","description":"CLI for preventive npm dependency risk scoring: registry metadata, lifecycle scripts, OSV, typosquatting heuristics","directories":{},"_nodeVersion":"20.20.0","dependencies":{"cac":"^6.7.14","chalk":"^5.4.1","pacote":"^21.0.0","semver":"^7.7.1","p-limit":"^6.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.7.3","tsx":"^4.19.3","tsup":"^8.4.0","vitest":"^3.0.9","typescript":"^5.8.2","@types/node":"^22.13.10","@types/semver":"^7.5.8"},"_npmOperationalInternal":{"tmp":"tmp/depguard_0.2.0_1774153877842_0.6157483099032692","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@azlabs/depguard","publishConfig":{"access":"public"},"version":"0.1.2","description":"CLI for preventive npm dependency risk scoring: registry metadata, lifecycle scripts, OSV, typosquatting heuristics","type":"module","bin":{"depguard":"dist/cli.js"},"main":"./dist/cli.js","types":"./dist/cli.d.ts","scripts":{"build":"tsup","dev":"tsx src/cli.ts","test":"vitest run","eval:metrics":"tsx scripts/eval-metrics.mts","generate:popular":"tsx scripts/generate-popular-packages.mts","prepublishOnly":"npm run build"},"engines":{"node":">=18"},"keywords":["npm","security","supply-chain","dependencies","audit","cli"],"license":"MIT","dependencies":{"cac":"^6.7.14","chalk":"^5.4.1","p-limit":"^6.2.0","pacote":"^21.0.0","semver":"^7.7.1"},"devDependencies":{"@types/node":"^22.13.10","@types/semver":"^7.5.8","msw":"^2.7.3","tsup":"^8.4.0","tsx":"^4.19.3","typescript":"^5.8.2","vitest":"^3.0.9"},"repository":{"type":"git","url":"git+https://github.com/matheusPavaneli/depguard.git"},"homepage":"https://github.com/matheusPavaneli/depguard","bugs":{"url":"https://github.com/matheusPavaneli/depguard/issues"},"_id":"@azlabs/depguard@0.1.2","gitHead":"da3cf6629c7545166807df0034d0f8d06019aca9","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-gqvZJu3QObRLF0jnIjTMhaTz1uLvjHZVRJNqY5stxlMsGhhi9JdPU2lNevtAsEKD79ZSYwsj4eY+h2KAVdxcuw==","shasum":"6ba42663fa229e2154cb602f0af94c9d1da3abe2","tarball":"https://registry.npmjs.org/@azlabs/depguard/-/depguard-0.1.2.tgz","fileCount":6,"unpackedSize":124100,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDhkirt/ApVYumIuB2T3fxoDSzbyY5Bdudf2MhtG8CwgQIhAPa+ChGvKgW1boFN2r6/ZgefQ35ulcL9Rt6sx5mic78W"}]},"_npmUser":{"name":"matheusaz","email":"matheuspavaneli@proton.me"},"directories":{},"maintainers":[{"name":"matheusaz","email":"matheuspavaneli@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/depguard_0.1.2_1774154190754_0.09744122951854339"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-22T04:03:21.097Z","modified":"2026-03-22T04:36:31.074Z","0.1.0":"2026-03-22T04:03:21.297Z","0.2.0":"2026-03-22T04:31:18.004Z","0.1.2":"2026-03-22T04:36:30.921Z"},"license":"MIT","keywords":["npm","security","supply-chain","dependencies","audit","cli"],"description":"CLI for preventive npm dependency risk scoring: registry metadata, lifecycle scripts, OSV, typosquatting heuristics","maintainers":[{"name":"matheusaz","email":"matheuspavaneli@proton.me"}],"readme":"# depguard\r\n\r\nnpm package: **`@azlabs/depguard`**. The installed CLI command remains **`depguard`**.\r\n\r\n**depguard** is a Node.js CLI that scores npm dependencies on a **0–100 trust scale** using public data only. It complements reactive tools such as `npm audit` and Dependabot by highlighting *risk signals before a CVE exists*: very new releases, low download counts, suspicious `postinstall` scripts, names similar to popular packages (typosquatting), and **known vulnerabilities** from the [Open Source Vulnerabilities (OSV)](https://osv.dev/) database.\r\n\r\nIt does **not** prove that a package is malware. It helps teams prioritize manual review and safer install workflows with clear, structured reasons for each flag.\r\n\r\n---\r\n\r\n## Features\r\n\r\n| Capability | Description |\r\n|------------|-------------|\r\n| **Dependency resolution** | Reads `package.json` and prefers **`package-lock.json`** (v2/v3) for exact versions; without a lockfile, resolves ranges via **pacote** (network). |\r\n| **Registry metadata** | Version publish time, maintainer count, weekly download estimate (npm downloads API). |\r\n| **Lifecycle script heuristics** | Scans `preinstall` / `install` / `postinstall` / related fields for patterns such as remote download + shell, `eval`, risky PowerShell usage, etc., with allowances for common native build tools. |\r\n| **Typosquatting** | Normalized string similarity (Levenshtein-based) against a curated list of popular package names; list can be **regenerated** from npm search (`npm run generate:popular`). |\r\n| **OSV integration** | Per `name@version`, queries `https://api.osv.dev/v1/query` for the npm ecosystem; results add a dedicated flag and score penalty. |\r\n| **Configurable thresholds** | `warnThreshold`, `blockThreshold`, `strict` mode, `trustedPackages`, optional OSV disable. |\r\n| **Install guard** | `depguard install` runs the audit first and can **prompt** (or abort with `--yes`) when scores fall below `blockThreshold`. |\r\n| **Feedback export** | `--export-feedback` writes anonymized JSON for GitHub issues ([template](.github/ISSUE_TEMPLATE/false-positive.yml)). |\r\n| **Eval harness** | `fixtures/eval-dataset.csv` + `npm run eval-metrics` for precision/recall/F1 on a small public labeled set (optional `STRICT_EVAL=1`). |\r\n\r\n---\r\n\r\n## Requirements\r\n\r\n- **Node.js 18+**\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install -g @azlabs/depguard\r\n```\r\n\r\nOr run without global install:\r\n\r\n```bash\r\nnpx @azlabs/depguard@latest audit\r\n```\r\n\r\nFrom a clone of this repository:\r\n\r\n```bash\r\nnpm install\r\nnpm run build\r\nnode dist/cli.js audit --cwd /path/to/your/project\r\n```\r\n\r\n---\r\n\r\n## Usage\r\n\r\n```bash\r\ndepguard audit\r\ndepguard audit --cwd ./my-app\r\ndepguard audit --strict\r\ndepguard audit --json\r\ndepguard audit --no-osv\r\ndepguard audit --export-feedback\r\ndepguard audit --export-feedback ./report.json\r\n\r\ndepguard install\r\ndepguard install -- --legacy-peer-deps\r\n```\r\n\r\n### Commands\r\n\r\n- **`audit`** — Resolve dependencies, fetch metadata (+ OSV unless disabled), print scores and human-readable flags (or JSON with `--json`).\r\n- **`install`** — Same audit pipeline, then spawns `npm install` with remaining arguments. If any package is below `blockThreshold`, the CLI asks for confirmation unless `--yes` is set (in which case it **exits without installing**).\r\n\r\n### Exit codes\r\n\r\n- **`audit`**: `0` normally; `1` if `--strict` and any package matches the internal **alert rule** (low score *or* OSV flag present).\r\n- **`install`**: inherits npm’s exit code after a successful audit path, or `1` when aborted by policy or strict audit failure.\r\n\r\n---\r\n\r\n## How scoring works\r\n\r\n1. Start from **100**.\r\n2. Apply **capped** penalties per category (age of the resolved version, downloads, single maintainer, typosquat similarity, script findings, OSV hits). Caps avoid driving every package to zero.\r\n3. **Young version** penalties are **scaled down** when weekly downloads are high (to reduce false positives on legitimate releases of popular packages).\r\n4. **`trustedPackages`** (case-insensitive names) skips metadata and typosquat penalties only; **OSV and script analysis still apply**.\r\n\r\nDefault thresholds are defined in [`src/config.ts`](src/config.ts) (`warnThreshold: 58`, `blockThreshold: 40`) and were tuned against [`fixtures/eval-dataset.csv`](fixtures/eval-dataset.csv).\r\n\r\n---\r\n\r\n## Configuration\r\n\r\nOptional files at the project root: **`guard.config.json`** or **`depguard.config.json`**.\r\n\r\n```json\r\n{\r\n  \"blockThreshold\": 40,\r\n  \"warnThreshold\": 58,\r\n  \"strict\": false,\r\n  \"trustedPackages\": [\"my-internal-scope-pkg\"],\r\n  \"includeDevDependencies\": true,\r\n  \"includeOptional\": true,\r\n  \"includePeer\": false,\r\n  \"includeOsv\": true,\r\n  \"concurrency\": 10\r\n}\r\n```\r\n\r\n| Field | Role |\r\n|-------|------|\r\n| `blockThreshold` | Below this score, `depguard install` prompts (or fails with `--yes`). |\r\n| `warnThreshold` | Used for `--strict` and for the eval script’s `predictAlert` baseline. |\r\n| `trustedPackages` | Suppresses registry “noise” rules for listed names; **not** OSV or dangerous scripts. |\r\n| `includeOsv` | Set `false` or use `--no-osv` to skip OSV HTTP calls (offline / faster runs). |\r\n\r\n---\r\n\r\n## Evaluation metrics (optional)\r\n\r\nLabeled rows live in [`fixtures/eval-dataset.csv`](fixtures/eval-dataset.csv). With network access:\r\n\r\n```bash\r\nnpm run eval:metrics\r\nSTRICT_EVAL=1 npm run eval:metrics\r\n```\r\n\r\nA GitHub Actions workflow ([`.github/workflows/eval.yml`](.github/workflows/eval.yml)) can run the same check on demand.\r\n\r\n---\r\n\r\n## Regenerating the popular-package list\r\n\r\n```bash\r\nnpm run generate:popular\r\n```\r\n\r\nMerges npm `/-/v1/search` results (keyword batching with a short delay) into [`src/data/popular-packages.ts`](src/data/popular-packages.ts).\r\n\r\n---\r\n\r\n## Limitations\r\n\r\n- **False positives** are expected for legitimate young packages or benign `postinstall` steps; tune thresholds and `trustedPackages`.\r\n- **Typosquat detection** is only as good as the embedded or regenerated name list.\r\n- **Private registries** or missing public packuments produce fetch errors and reduced signal.\r\n- **No tarball/static analysis** in this version; unknown malware without manifest signals may not be flagged.\r\n\r\n---\r\n\r\n## Development\r\n\r\n```bash\r\nnpm install\r\nnpm run build\r\nnpm test\r\n```\r\n\r\n- **Build**: `tsup` bundles the CLI to `dist/cli.js` (ESM) with external runtime deps (`cac`, `chalk`, `p-limit`, `pacote`, `semver`).\r\n- **Tests**: `vitest` + `msw` for HTTP mocks.\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md","homepage":"https://github.com/matheusPavaneli/depguard","repository":{"type":"git","url":"git+https://github.com/matheusPavaneli/depguard.git"},"bugs":{"url":"https://github.com/matheusPavaneli/depguard/issues"}}