Package Safety Gate (npm, PyPI, crates.io) avatar

Package Safety Gate (npm, PyPI, crates.io)

Pricing

from $5.00 / 1,000 package checks

Go to Apify Store
Package Safety Gate (npm, PyPI, crates.io)

Package Safety Gate (npm, PyPI, crates.io)

Pre-install check for npm, PyPI and crates.io packages. Catches hallucinated and typosquatted names, flags install scripts, advisories and young packages, and returns allow, warn or block. Decision support only.

Pricing

from $5.00 / 1,000 package checks

Rating

0.0

(0)

Developer

Chris O'Byrne

Chris O'Byrne

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

What does Package Safety Gate do?

Package Safety Gate is a pre-install check for npm, PyPI and crates.io packages. Call it before an AI coding agent or a developer runs npm install, pip install or cargo add. It looks up each package in its public registry and other open data sources, then returns a verdict (allow, warn or block) with a plain list of reasons.

It is built to catch the problems that agents and busy developers hit most often:

  • Hallucinated package names. A name that does not exist in the registry is reported as exists: false with a block verdict. Attackers register such names ("slopsquatting"), so installing a made-up name is risky.
  • Typosquats. Names that sit one or two edits away from a popular package (transposed letters, look-alike characters, dropped separators, scope tricks) are listed with the popular package they resemble.
  • Risky packages. Brand-new packages, very low download counts, install-time scripts (npm), known advisories and malicious-package records from OSV, deprecated or yanked versions, and low OpenSSF Scorecard scores.

A verdict is decision support only. It is a heuristic summary of public data. It is not a security audit, it does not read package code, and it cannot promise that a package is safe or unsafe. Read the reasons and make the call.

Who is it for?

  • Teams that run AI coding agents and want a gate before dependencies are added.
  • Developers who want a quick sanity check on an unfamiliar dependency.
  • CI jobs that review a package.json, requirements.txt or Cargo.toml change.

How to use it

  1. Choose a mode: package-check or lockfile-check.
  2. For package-check, list packages as {"ecosystem": "npm", "name": "express"} objects. A version is optional and can be an exact version, a range or a tag. The short form npm:express@4.18.2 also works.
  3. For lockfile-check, paste up to 50 dependencies as name@version lines, or paste a package.json, requirements.txt or Cargo.toml.
  4. Run the Actor and read the dataset (table view "Verdicts"). The key-value store record OUTPUT holds a run summary with counts and the worst verdict.

You can also call it from code or from an AI agent through the Apify API or the Apify MCP server. Example with the API (add your own token):

curl -X POST "https://api.apify.com/v2/acts/jetlaunch~package-safety-gate/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"package-check","packages":[{"ecosystem":"npm","name":"express"}]}'

Input

FieldMeaning
modepackage-check or lockfile-check
packagespackage-check only. Up to 100 entries of {ecosystem, name, version?} or "npm:name@version" strings. Ecosystems: npm, pypi, crates
lockfilelockfile-check only. Up to 50 dependencies, pasted as text
lockfileFormatauto, lines, package.json, requirements.txt, Cargo.toml
ecosystemNeeded for plain lines and requirements.txt text. package.json is npm and Cargo.toml is crates.io

The default input checks express (npm), requests (PyPI) and a name that does not exist, so you can see an allow and a block verdict in one run.

Output

One dataset item per package. A shortened example for a hallucinated name:

{
"ecosystem": "npm",
"name": "zq-hallucinated-pkg-91827",
"status": "ok",
"verdict": "block",
"exists": false,
"reasons": [
{
"code": "not-found",
"severity": "block",
"message": "Package \"zq-hallucinated-pkg-91827\" does not exist on the npm registry. A name that does not exist is a common sign of a hallucinated dependency, and registering it would let an attacker supply the code."
}
],
"typosquat": { "isPopularPackage": false, "neighbours": [] },
"disclaimer": "Decision support only, not a security guarantee."
}

For a package that exists you also get: resolvedVersion, ageDays, firstPublishedAt, latestVersion, latestVersionDate, weeklyDownloads (with its basis), maintainerCount, installScripts (npm: which of preinstall, install and postinstall are present), advisories (count, highest severity, malware flag, OSV ids and links), scorecard (OpenSSF Scorecard score when a GitHub repository is linked), repository, license, and typosquat (whether the package is itself popular, and the closest popular names with the kind of match).

Reasons carry a severity: block, warn or info. The verdict is the highest severity present.

The output contains no free text written by package authors (no descriptions, no script bodies), so it is safe to hand to an AI agent without prompt-injection risk from package metadata.

Pricing

This Actor uses pay-per-event pricing. You pay only for the events below, plus nothing for failed lookups.

EventPriceWhen it is charged
Package check$0.005Once per package that returns a verdict, including a verdict for a name that does not exist
Lockfile check$0.03Once per lockfile check of up to 50 dependencies, when at least 80% of the registry lookups succeed

Not charged: entries with an invalid name or ecosystem, lookups where the registry could not be reached, and lockfile runs where fewer than 80% of lookups succeeded. If you set a maximum cost per run, the Actor stops cleanly when the limit is reached.

How verdicts are decided

SignalEffect
Package or exact version not found, or unpublishedblock
OSV malicious-package record for the version, or npm security placeholderblock
Very close name to a popular package, little adoption (under 1,000 weekly downloads), and young (under 180 days) or no linked repositoryblock
Close name to a popular packagewarn (info if the package is well adopted)
First published under 30 days ago, under 100 weekly downloadswarn
npm install scripts (info for packages with over 1 million weekly downloads)warn
Known advisories with HIGH or CRITICAL severity for the checked versionwarn (other severities: info)
Deprecated or yanked versionwarn
OpenSSF Scorecard under 3warn (info for packages with over 1 million weekly downloads)
OSV could not be reachedwarn
No repository link, one maintainer on a young package, stale for 3 years, very new versioninfo

Data sources and licences

The Actor uses official public APIs only and paces its requests. Each request carries a User-Agent that names this Actor and a contact address.

  • npm registry and the npm downloads API (api.npmjs.org). Registry requests are limited to 1 per second per run, in line with npm's crawler policy.
  • PyPI JSON API and pypistats.org for download counts (the pypistats etiquette asks clients to avoid bulk crawling; this Actor looks up only the packages you submit).
  • crates.io: the sparse index first, then the API only for downloads, repository and owner counts, with at most 1 API request per second and an identifying User-Agent, as the crates.io data access policy requires.
  • OSV (api.osv.dev). Each advisory keeps the licence of its source database.
  • deps.dev API (Google). Generated data is available under CC-BY 4.0. Use is subject to the Google API Terms of Service.
  • OpenSSF Scorecard API (api.scorecard.dev). Data is licensed under CDLA Permissive 2.0.
  • Popular-name lists for typosquat checks are bundled: the top 3,000 npm names (from the MIT-licensed npm-high-impact package), the top 3,000 PyPI names (from the monthly hugovk/top-pypi-packages ranking) and the top 1,500 crates by downloads (from the crates.io API). The list date is stored in every run summary.

Package Safety Gate is not affiliated with or endorsed by npm, PyPI, the Python Software Foundation, crates.io, the Rust Project, Google, OSV, deps.dev or the OpenSSF. Product names are used only to describe what is checked.

FAQ

Does it scan package code? No. It uses registry metadata, advisories, popularity and name similarity. It reports whether an npm version declares install scripts but does not read them.

Why does a popular package sometimes get a warning? Install scripts, deprecated versions or known advisories can apply to any package. Read the reasons.

Why is maintainerCount empty for some PyPI packages? PyPI reports owners only for the project, and organization-owned projects show no individual owners. The field is left empty rather than guessed.

How are crates.io weekly downloads calculated? crates.io publishes a 90-day total. The weekly figure is that total divided by 90 and multiplied by 7, and the output says so.

How are version ranges handled? npm and crates.io ranges are resolved against the published versions. For PyPI only exact pins (==) are resolved; other specifiers are checked against the latest version, and the output says how the version was chosen.

How long does a run take? Requests are paced to respect the upstream limits. In platform test runs a 50-dependency list took about 55 seconds for npm, about 77 seconds for PyPI and about 110 seconds for crates.io. A single package takes a few seconds.

Limitations

  • Only the public registries listed above. Private registries, git, URL and path dependencies are reported as not checkable.
  • The typosquat check compares against bundled popular-name lists, not the whole registry.
  • Scorecard results exist only for GitHub repositories that Scorecard has analyzed.
  • A new malicious package that no advisory database knows yet can still receive allow. That is why the verdict is decision support only.

Support

Open an issue in the Issues tab of this Actor. Include the input you used and the run ID.