# VulnerableCode: a free vulnerability database keyed by package, not by product

> VulnerableCode is an open source database of software package vulnerabilities with a web interface and an API, and its organising idea is to key everything on the Package URL so you can ask whether a specific package version is affected. It is a Django and PostgreSQL application with many import pipelines and a public instance.

**aboutcode-org/vulnerablecode** — A free and open vulnerabilities database and the packages they impact. And the tools to aggregate and correlate these vulnerabilities. Sponsored by NLnet https://nlnet.nl/project/vulnerabilitydatabase/ for https://www.aboutcode.org/ Chat at https://gitter.im/aboutcode-org/vulnerablecode  Docs at https://vulnerablecode.readthedocs.org/

- Repository: https://github.com/aboutcode-org/vulnerablecode
- Website: https://public.vulnerablecode.io
- Stars: 712 · Forks: 346
- Language: Python
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/aboutcode-org-vulnerablecode

## A database organised by package rather than by product

VulnerableCode is a database of software package vulnerabilities with a web interface and an API, and the argument for it is made in the README in three steps.

The first is that vulnerability databases have traditionally been proprietary even though they are mostly about free and open source software. The second is that these databases often contain a lot of lesser value data, which means a lot of false positive signals that require extensive expert review. The third is the one that matters most for the design: vulnerability databases are mostly about vulnerabilities first and software packages second, which makes it difficult to find if and when a vulnerability applies to a piece of code.

The response is the ordering. VulnerableCode's focus is on software packages first, where a Package URL is the key and natural identifier for packages, and the stated benefit is that it makes it easier to find a package and whether it is vulnerable.

The Package URL specification was designed initially for ScanCode and VulnerableCode, and is now a standard for vulnerability management and package references. That origin is worth knowing, because it explains why the identifier is in the centre of the data model rather than bolted on. A PURL encodes the type, the namespace, the name and the version of a package, so the question the database is built to answer is a lookup, not a search.

The project is Apache-2.0 licensed for the code, the primary language is Python, the default branch is main, and the last push was on 2026-10-20 with releases 40.0.1, 40.1.0 and 40.2.0 in July, September and October 2026. The version number is a useful signal: this is a mature application with a long release history rather than a new project.

## The stack, and the shape of the deployment

The tech stack is Python, Django, PostgreSQL, nginx and Docker, plus a set of libraries, and the compose file shows how those pieces are arranged for a real deployment.

There are separate services for the database, which is postgres:15 with a mounted configuration file, the web application, a scheduler, two workers with different queue names, Redis and nginx. The web service runs the migrations, collects the static files and then starts gunicorn bound to port 8000 with a 600 second timeout and 8 workers, running as the nobody user.

The worker split is the interesting bit. There is a default worker running the queue named default and a second one running the queue named high, and the scheduler is a separate process waiting for the web service before starting. That layout is a direct consequence of how the import pipelines work, where a bulk import from one source should not be blocked behind per-record work from another.

The Redis service exists for the background job queue, and the rq and rq-scheduler packages in the requirements confirm the mechanism. The nginx service terminates TLS on port 443 and serves port 80, with the static volume shared into the web container.

The requirements file is long and tells you what the project leans on. Django 5.2.11, djangorestframework with drf-spectacular for the API, django-filter, django-rq, django-environ for configuration, psycopg2-binary, gunicorn, celery's alternative rq and its scheduler, and the AboutCode family of packages: aboutcode.pipeline at 0.1.0, aboutcode.federated at 1.0.3, commoncode, extractcode, fetchcode, plugincode, typecode and univers.

Those AboutCode packages are the reason the project can ingest and serve file and package metadata, and the presence of packageurl-python at 0.17.6 confirms that the PURL type is a first class citizen in the code.

## Dozens of importers, and the ones with a doctest problem

The import side is where the scale shows. The pytest configuration ignores a long list of importer modules, and the list reads as a catalogue of the advisory sources the project consumes: apache_httpd, apache_kafka, apache_tomcat, elixir_security, gentoo, istio, kaybee, npm, postgresql, project_kb_msr2019, retiredotnet, ruby, rust, suse_backports, suse_scores, ubuntu_usn and mozilla.

Those are the sources that get their advisories from a distribution package rather than from a single upstream feed, which is where the complexity lives. A Debian security advisory and a Gentoo advisory describe the same upstream vulnerability with different package names, different version schemes and different fix versions, and reconciling them is the hard part of a project like this.

The comment above the ignore list explains why they are excluded, and it is a useful detail. They are doctests that are ignored until those files are migrated to the import-improve structure. So the codebase is mid-migration, and a chunk of the importers still carry a documentation style that the new structure does not accept.

That has a practical consequence for anyone planning to contribute. The project documents tutorials for adding new pipelines to import and improve advisories, and the mention of an import-improve structure implies a convention for how importers should be written. A new importer written in the older style would land in the same backlog.

The top level of the repository reinforces the shape. There is a vulnerabilities/ directory, a vulnerablecode/ directory which holds the Django project, an aboutcode/ directory, and a vulntotal/ directory, plus a PIPELINES-AVID.rst file and an SOURCES.rst file, which are the two documents that describe the pipeline inventory and the upstream sources.

## The API, the web interface and the public instance

There is a public VulnerableCode database at public.vulnerablecode.io, and the project also provides the tools to build your own instance of the database. That split is the point of the project, since the code and the data are both open.

The documentation covers how to use the API, an introduction to the user interface, and there is an api_v3_usage.rst file in the repository, so the API is versioned and there is a document describing the third version. The API stack is Django REST Framework with drf-spectacular, which means the schema is generated from the serializers rather than written by hand, and drf-spectacular is what produces the OpenAPI document.

The web interface is a Django application with crispy forms, django-filter for the query filtering, and django-widget-tweaks for form rendering. django-altcha and the altcha package are in the requirements, which is a captcha implementation used for the sign-up and login forms, and that is a sensible thing for a public service with user accounts.

The documentation list is worth reading as a description of scope. There are prerequisites for installing the software, an introduction to the user interface, how to use the API, tutorials for adding new pipelines, extensive reference information about the VulnerableCode data, and guidelines for contributing to code development. The reference section on the data is the one to check first, because the shape of a vulnerability record, how affected versions are expressed, and how fixes are linked are the things you need before you write a query against the API.

The getting started instructions are in the documentation site rather than the README, at the stable branch of the readthedocs build, which means the setup path lives in versioned prose rather than in the repository.

## The licensing split, which is the thing to read carefully

The licence section is three bullets and the distinction between them matters for anyone redistributing data or code.

The code is under Apache-2.0, with the licence file in the repository. The reference datasets are under CC-BY-SA-4.0, also with its licence file present. And there are multiple secondary permissive or copyleft licences, LGPL, MIT, BSD, GPL 2 and 3 among them, applying to third party components and to the test suite code and data.

That middle bullet is the one people get wrong. The data VulnerableCode ships is not under the same terms as the code, and a copyleft share-alike licence on the datasets is a clearly different obligation from Apache-2.0 on the software. If you are building a product that embeds vulnerability records, the attribution and share-alike terms on the reference data apply to that data, whatever you do with the code around it.

There is a NOTICE file at the top level as well, which is the standard Apache-2.0 mechanism for recording third party attributions, and the top level also carries AUTHORS.rst, a CHANGELOG.rst, a CODE_OF_CONDUCT.rst, a MANIFEST.in, a Makefile, a Dockerfile, a docker-compose.yml and a docker.env, along with a separate pyproject-aboutcode.hashid.toml alongside the main pyproject.toml.

The hashid file is worth a note. The name suggests it exists to pin or override dependency hashes for the AboutCode packages, which is a common pattern in projects that need reproducible builds across a set of related repositories that release independently.

## Where VulnerableCode is the wrong choice

The first wrong case is a real-time advisory feed for a build pipeline. VulnerableCode is a periodically imported database, and the value of importing and reconciling many sources is inherently at odds with freshness. A scanner that needs to know about a vulnerability published an hour ago wants the upstream feed, not a database that was last imported this morning. The trade is coverage and reconciliation against latency, and for a build gate, latency is what you are buying.

The second is a small team that does not want to run a Django and PostgreSQL application. There is a public instance, so you can query it rather than deploy it, but you are then dependent on somebody else's uptime and on the freshness of their import cycle. The project offers the tools to build your own instance, and that is a real operation with Postgres, Redis, workers, a scheduler and nginx in front of it.

The third is a need for commercial support guarantees. The project is funded through a series of NLnet programmes and grants, with support from the European Commission NGI programme, the Swiss State Secretariat for Education, Research and Innovation, Google including the Summer of Code and the Seasons of Doc programmes, Mercedes-Benz Group, Microsoft and Microsoft Azure, AboutCode ASBL and nexB Inc. The commercial support path is offered through the AboutCode team, which is a real option, but it is a company rather than a vendor contract with an SLA.

The fourth is a codebase that assumes the data is complete. The README says the databases contain a lot of lesser value data producing false positives that need expert review. VulnerableCode reduces that by being package-first, but a record's existence is not a claim that your code is exploitable, and the reference documentation on the data is where you would find out what a given field does and does not mean.

## Conclusion

Adopt VulnerableCode if your work needs to answer whether a specific package version is affected by a known issue, since its Package URL keying is the feature commercial databases do not offer, and the public instance gives you a queryable database before you build anything. Keep away if you need a real-time feed of new advisories for your build pipeline, because this is a periodically imported database rather than a subscription service, and the import latency is the gap. Before you deploy your own instance, read the pipelines documentation, and note that the code is Apache-2.0 while the reference datasets are CC-BY-SA-4.0, so the two licences apply to different parts of what you ship.

## FAQ

### What is VulnerableCode and what is its central idea?

It is a free and open database of open source software package vulnerabilities with a web UI and an API, plus the tools to build your own instance. The central idea is that the database is organised around software packages first, with a Package URL as the key and natural identifier, rather than around vulnerabilities first, which the README says makes it hard to tell whether a vulnerability applies to a piece of code.

### What is the tech stack behind VulnerableCode?

Python, Django, PostgreSQL, nginx and Docker, with a set of libraries. The compose file runs postgres:15, a web service on gunicorn bound to port 8000 with 8 workers, a scheduler, two RQ workers on different queues, Redis, and nginx in front. The requirements include Django 5.2.11, Django REST Framework with drf-spectacular, packageurl-python and the AboutCode packages such as commoncode, extractcode and fetchcode.

### Under which licence are the VulnerableCode code and data?

The code is Apache-2.0 and the reference datasets are CC-BY-SA-4.0, with separate licence files for each. There are also multiple secondary permissive or copyleft licences applying to third party components and to the test suite code and data.

### How do I add a new advisory source to VulnerableCode?

The documentation provides tutorials for adding new pipelines to import and improve advisories, and the pytest configuration shows that a number of existing importer modules are ignored until they are migrated to the import-improve structure, so the convention matters when writing a new importer.

## Sources

- [aboutcode-org/vulnerablecode on GitHub](https://github.com/aboutcode-org/vulnerablecode)
- [License: Apache-2.0](https://github.com/aboutcode-org/vulnerablecode/blob/main/LICENSE)
- [Project website](https://public.vulnerablecode.io)
- [README](https://github.com/aboutcode-org/vulnerablecode/blob/main/README.md)
- [Releases](https://github.com/aboutcode-org/vulnerablecode/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/aboutcode-org-vulnerablecode
