CLI tool
pyupio/safety-db avatar
pyupio/safety-db

safety-db: a curated list of known insecure Python packages

A curated database of insecure Python packages

785 stars86 forksPythonNOASSERTION

At a glance

What is it?
Safety DB is a monthly synced dataset of Python packages with known security vulnerabilities, published both as a browsable website and as two JSON files, one plain list and one carrying CVE descriptions and changelog excerpts. The data is licensed CC BY-NC-SA 4.0, which makes it free for non-commercial use with attribution and needs a conversation for commercial use.
Who is it for?
Use Safety DB if you want a curated, human-reviewed list of vulnerable Python releases to check against your own dependency inventory, or to feed into a scanner that needs a non-commercial-friendly source of truth. Do not build a commercial scanning product on the published data without contacting pyup.io first, because the CC BY-NC-SA 4.0 terms restrict commercial use.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 22 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A curated list, not a scanner

Safety DB is a database of known security vulnerabilities in Python packages. The data is made available by pyup.io and synced with the repository once per month.

The curation method is what distinguishes it from a feed of raw vulnerability records. The README states that most of the entries are found by filtering CVEs and changelogs for certain keywords and then manually reviewing them. That is a small but meaningful amount of human judgement: a keyword filter over CVE text produces a lot of noise, and the review step decides which packages and which specific releases are actually affected.

The second half of the mechanism is the changelog. A package can ship a fix without a CVE ever being published, and the presence of a release note describing a security fix is often the only signal available. Collecting changelog excerpts alongside CVE records is what lets the database point at the specific release where a fix landed.

The project is also careful to frame what it is not. The README says this is not a hall of shame, or a list of packages to avoid, and the reasoning is worth repeating because it changes how you use the data. The package maintainers show a great responsibility by documenting and fixing security issues in such a way that they can be listed here, and that is described as extremely valuable when considering using a package in production.

So the intended reading is: this is a record of fixed problems and the release that fixed them, which is exactly the information you need to decide whether a pinned version is safe, rather than a verdict on a package.

The data is public and hosted under pyup.io, and the repository itself is where the dataset lives, with the browsable website built from the same content.

Two JSON files, two levels of detail

The data directory holds the payload, and the README is explicit about the two shapes it comes in.

insecure.json contains just the package name and all insecure releases as a plain list. That is the compact form: for each affected package, the set of versions that should not be used. It is small, it is fast to load, and it is the right input for a check that only needs to compare versions.

insecure_full.json additionally contains the CVE description and URLs, or the relevant part of the changelog. That is the version you want when a human has to make a decision, because the entry explains itself: which advisory applies, where to read it, or what the maintainer wrote when the fix shipped.

The distinction matters for tooling. An automated gate wants the first file and nothing else, since it is matching installed versions against known bad releases. A report for a reviewer wants the second, because a bare version list with no explanation is not actionable.

The repository layout is small and consistent with a data package. There is a data directory, a docs directory, tests.py, setup.py, setup.cfg, MANIFEST.in, requirements.txt, a .travis.yml and a LICENSE.txt. The package metadata in setup.py maps the data directory to the importable package with package_dir set so that safety_db resolves to the data folder, and it ships the JSON files through include_package_data rather than embedding them in code.

For people who just want to look, the README points to a small website at pyupio.github.io/safety-db that lets you browse the data, which is a faster way to answer a one-off question about a specific package than cloning anything.

Installing the package and reading the data in code

The install is a single command from PyPI:

sh
pip install safety-db

And the usage is a two-name import:

python
from safety_db import INSECURE, INSECURE_FULL

The two constants mirror the two JSON files, which is the only API the package exposes. There is no client, no configuration and no network call, because the whole point is that the data is a snapshot you can vendor.

The packaging has a couple of details that explain how the version is handled. The setup.py does not hardcode a version. It opens data/__init__.py, applies a regular expression looking for a __version__ assignment, and raises a RuntimeError with the message Unable to find version string. if it cannot find one. The version therefore lives with the data, which is the sensible arrangement for a package whose content changes on a monthly sync.

The install_requires list is empty, and the test requirements are packaging and parameterized, which is also in requirements.txt. The classifiers cover Python 2.7 and Python 3.4 to 3.6, and the development status is given as Production/Stable.

Those classifiers are the clearest signal of the age of the packaging metadata, and they are worth checking against your own environment before you assume the installed package works on a current interpreter.

The tools that sit on top of the database

The repository is more useful as a data source than as a product, and the README lists the consumers that already exist.

Safety is the command line tool that checks virtual environments and requirement files, either locally or on a CI server. Safety CI is a deeper GitHub integration available on pyup.io that checks your commits and pull requests. Safety Django is a package for Django that warns you in the admin area if your installed Django release is insecure, which is a neat piece of design because it puts the warning where an administrator already is.

There is also a pre-commit hook for Safety by Lucas Cimon, and the README notes that pipenv check relies on Safety and Safety-DB to check for known vulnerabilities in locked components. A macOS menubar application called Safety Bar exists as well, and it is explicitly labelled alpha.

The list ends with your tool, which is the invitation the project is making. The data is deliberately exposed in a form that is easy to consume, both as a browsable site and as two JSON files, so that anyone can build a check on top of it.

What that means for an evaluation is that you are not choosing a scanner, you are choosing a dataset and possibly supporting tools. The scanners themselves have their own licensing and pricing, and the data licence below is a separate question from what the tools cost.

The CC BY-NC-SA term and the commercial question

The database is licensed under CC BY-NC-SA 4.0, and the README explains what that permits in plain terms: it allows you to use the data in any non-commercial project as long as you link back to the repository. If you need a licence for a commercial project, you are told to contact [email protected].

The setup.py records the same term as Attribution-NonCommercial-ShareAlike 4.0 International, so the non-commercial restriction is part of the package metadata as well as the README, and it will travel with the data if you redistribute it.

For most open source work this is a non-issue, and the attribution requirement is easy to meet. For a company scanning its own production dependencies, though, the line between commercial and non-commercial is exactly the kind of thing that gets argued, and the honest reading is that using this data inside a commercial product or a paid service needs permission from pyup.io rather than an interpretation of your own.

This is not legal advice, and the right move for an organisation is to ask the question in writing before shipping.

Two related points are worth keeping separate. The repository itself is classified by GitHub as carrying a custom licence that it cannot categorise, with the terms in the LICENSE.txt file, so the file is the authority on the data terms. And the underlying vulnerability records are themselves public information, but the curation, the JSON structure and the maintenance are pyup.io's work, and it is that work the licence attaches to.

Two dates that matter more than the badge

There is a gap in this project that you will notice if you look at the dates.

The repository is not archived and the last push was on 2026-10-01, consistent with the monthly sync the README describes. The published releases, however, list exactly one, 2021.7.17, the July 2021 release, published on 2021-07-18. So the data in the repository has been refreshed for years while the pip package has not been re-released since 2021.

That distinction decides how you use it. If you pip install safety-db, you get the snapshot as it was packaged then. If you read the JSON files from the data directory of the current checkout, you get the current data. For a security dataset, that is a meaningful difference, and the repository README itself directs robots to the data directory rather than to the installed package for exactly this reason.

The CI configuration shows the same era. There is a .travis.yml in the repository root and the build badge in the README points at travis-ci.org, the retired Travis CI domain, rather than the current service. The badge is a small thing, but it is another sign that the packaging and continuous integration side of the project stopped being refreshed while the data pipeline kept running.

The Python classifiers tell the same story from another angle, listing 2.7 and 3.4 through 3.6.

None of this undermines the dataset itself. It does mean you should treat the pip package as a historical artefact and the repository data as the live product, and it is worth noting that the README does not document a schema version or a change log for the JSON structure, so a consumer that parses it should be tolerant of new fields.

Editorial conclusion

Use Safety DB if you want a curated, human-reviewed list of vulnerable Python releases to check against your own dependency inventory, or to feed into a scanner that needs a non-commercial-friendly source of truth. Do not build a commercial scanning product on the published data without contacting pyup.io first, because the CC BY-NC-SA 4.0 terms restrict commercial use. Before you depend on the packaged version, check the release date, since the pip package was last released in July 2021 while the repository data syncs monthly, and prefer reading the JSON files in the data directory directly if you need current entries.

Frequently asked questions

What is Safety DB and how is the data produced?

It is a database of known security vulnerabilities in Python packages, made available by pyup.io and synced with the repository once per month. Most entries are found by filtering CVEs and changelogs for certain keywords and then manually reviewing them.

How do I install safety-db and read the vulnerability data?

Run pip install safety-db, then import the two constants with from safety_db import INSECURE, INSECURE_FULL. The package has no install requirements, and its version is read from data/__init__.py at build time.

What is the difference between insecure.json and insecure_full.json?

insecure.json contains just the package name and all insecure releases as a plain list, while insecure_full.json additionally contains the CVE description and URLs, or the relevant part of the changelog.

Can I use Safety DB data in a commercial project?

The database is licensed under CC BY-NC-SA 4.0, which allows use in any non-commercial project as long as you link back to the repository. For commercial use you need to contact [email protected] to obtain a licence, so ask before shipping it inside a paid product.

How current is the safety-db data and the published package?

The repository is synced with pyup.io once per month and the last push was on 2026-10-01, but the only published release is 2021.7.17 from July 2021. Reading the JSON files from the data directory of a current checkout gives you the newer data.

Official sources

  1. Issues
  2. Project website
  3. pyupio/safety-db on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pyupio-safety-db.svg)](https://hysenlabs.com/projects/pyupio-safety-db)

Was this useful?