On this page
About depcurfew
What depcurfew does not do
depcurfew makes the package managers' own protections work and checks a package's age, name, install scripts and source before it is installed. It does not scan package contents, and it has no malware database until you download one: after depcurfew osv update, check, the Claude Code hook, depcurfew mcp and doctor block the versions that a local copy of the OpenSSF malicious-packages data of OSV.dev lists, offline; with --osv (also the input osv of the Action) they ask OSV.dev itself. Without either, a malicious version older than the cooldown passes. Both catch only malware someone has found and reported, and the database admits false positives: see Known malicious versions. Keep npm audit or an equivalent for known vulnerabilities, which neither reports. depcurfew also does not run or sandbox anything: the protection comes from the configuration the package managers read.
Network and privacy
Only check, the Claude Code hook and the check_packages tool of depcurfew mcp use the network, doctor and the GitHub Action only with --osv (input osv: true), for OSV.dev alone, and depcurfew osv update only to download the public export files of OSV.dev from storage.googleapis.com, a request that holds nothing about you or the project. The lookups in the local data it writes need no network. For each package the first three request one URL with the package name in it: from the public npm registry (registry.npmjs.org), PyPI (pypi.org) or Packagist (repo.packagist.org), or from the registry that the project's or your .npmrc sets, --registry or --index. They send no credentials (tokens in .npmrc are not read, and the user part of a registry URL, a password with an unencoded @ and a token alone included, is removed before the request) and nothing else about the project, and depcurfew has no telemetry. No output of depcurfew shows credentials from a URL either: text, JSON, SARIF, diffs, the hook's answer, depcurfew mcp and what the GitHub Action sends show the user part of a URL as <redacted>. A private package whose scope has no registry in an .npmrc that npm reads is looked up in the public registry, so its name reaches that registry; set @scope:registry in .npmrc or pass --registry first. A package whose scope has a registry in an .npmrc that check does not take, or in .yarnrc.yml or bunfig.toml, or one that the .npmrc depcurfew takes assigns to another registry than the one it asks, is not looked up, and neither is a package that a registry or index of the environment or of a user or global configuration file points elsewhere (see Guarding installs), nor a Composer package when the root composer.json declares another repository or turns packagist.org off. With --osv they also send the name, ecosystem and version of each package to api.osv.dev in a batch query, and doctor --osv those of every locked package version, private packages included (see Known malicious versions); without --osv nothing goes to OSV.dev. init, explain, apply and doctor without --osv work without network access. The GitHub Action checks the repository without it too, unless the input osv is true; afterwards it sends the result (the counts, the table of checks and findings, the files read) to the GitHub API of the run (GITHUB_API_URL) with the workflow token to create the depcurfew doctor check (input check-run), and the SARIF upload to code scanning is a separate step that runs GitHub's own action. An editor that reads the $schema of depcurfew.json may download the schema from unpkg.com.
depcurfew uses the fetch of Node.js, which goes through the proxy of HTTPS_PROXY and HTTP_PROXY only when NODE_USE_ENV_PROXY=1 is set (or Node.js runs with --use-env-proxy), from Node.js 22.21.0 and 24.0.0; older Node.js has no such switch. Without it, on a network that is reached only through a proxy, the registry cannot be reached: check exits with 1 and the hook asks, as for any lookup that fails, and depcurfew osv update keeps the data it has.
Library
The same functions are available from the package: detectProject, planApply and applyProject, runDoctor with toSarif (and runDoctorWithOsv, doctor --osv, and runDoctorWithLocalOsv with LocalOsvData, the local OSV.dev data, defaultOsvData, the data of the user cache directory, and updateOsvData, depcurfew osv update), checkSpecs with scanCommandLine and defaultPopularNames, queryOsv, and the policy parser and converters. runDoctor compares a repository without depcurfew.json with a policy, as depcurfew doctor does, only when it gets one as the option defaultPolicy (for example the policy that parsePolicy(renderPolicy(DEFAULT_POLICY)) returns); without it the rules that need a policy do not run. Their types ship in dist/index.d.ts, and src/index.ts lists every export. The package is an ES module only: use import; require('depcurfew') works on Node.js 22.12 and later, which load ES modules with require().
Semantic versioning covers getVersion, loadPolicy, checkSpecs and PopularNames, with the shapes of their options and results, whose types the package names: CheckOptions, CheckRequest, FetchLike, PackageReport, CheckFinding, FindingCode and SpecKind. A minor or patch release may add optional options, fields of a result, codes and kinds, and never removes or renames one, makes an option required or gives a finding a level other than error or warning. The other exports may change in a minor release, with a line under Library in the changelog.
A program that checks packages without the network, as agentcurfew does for the packages of MCP servers, passes checkSpecs a fetch that refuses every request and the popular names depcurfew's own commands use: checkSpecs(specs, { ...defaultPopularNames(), policy, fetch, now, registry }). Sources the policy denies, specs that are not specs and names that imitate a popular npm package or PyPI project are reported then, since they need no registry, and every other package as unverified. pypi:. and pypi:.[extras] count as the project itself unless the options say projectRoot: false, for packages installed in a directory that is not the root of a project, where they are a local directory. defaultOsvData() returns the LocalOsvData of the data depcurfew osv update wrote to depcurfew's user cache directory, or undefined when nothing was downloaded: lookup({ ecosystem: 'npm', name, version }) gives the ids of the OSV.dev malicious-package records of that version (the ecosystems are npm, pypi and packagist; for any other name state is missing and lookup gives undefined, and no file is read), and writeProblem() says when other users can write a directory of the data, which would let them change what the lookups find.
Contributing
Facts about package managers live only in src/knowledge/, each with the official URL it was verified against and the date. A correction is welcome with a link to the official documentation or changelog. npm test builds the project and runs every test without network access. CONTRIBUTING.md has the setup, the commands and the rules for changes, and the issue forms ask for what a report needs; vulnerabilities go through SECURITY.md.
npm run site builds the documentation site into dist-site/ from this README, the knowledge base and schema.json, so its pages say what the README says; its pages link to each other with relative links, need no JavaScript and load nothing from other hosts, so the logo and the badges at the top of this README are left out. Since homepage in package.json is the address of the site, each page of the current version names its address there as the canonical one and has its own description, and the site has robots.txt, sitemap.xml with the pages of the current version and a 404.html whose links start at the root of the site. npm run site -- --versions also reads the release tags with git and adds the README, knowledge base, changes and schema of every earlier release from 1.1.0 on under /<version>/, each page with a banner that names its version and marked noindex, so that search engines list the current documentation, and a Versions page. The site is published at depcurfew.github.io by the repository depcurfew/depcurfew.github.io, which builds it from the main branch of this repository once a day and on demand, so a merged change to the documentation appears without a release; while the main branch is not the release of its version, every page says so in a banner that links to the documentation of the latest release (its files are in site/org-repo/) and serves the schema at schema.json and schema/v1.json.
License
Trademarks
npm is a registered trademark of npm, Inc. "Python" and "PyPI" are trademarks of the Python Software Foundation. pnpm, Yarn, Bun, Deno, uv, pip, Poetry, PDM, Pipenv, Composer, Packagist, Renovate, Dependabot, GitHub, Claude Code and the other names in this document belong to their owners. depcurfew is an independent project and is not affiliated with or endorsed by any of them.