├── test ├── __init__.py ├── data │ ├── CVE-2021-3618.json │ ├── CVE-2022-27400.json │ ├── CVE-2023-21500.json │ ├── AVG-999.json │ ├── protobuf-c.json │ ├── DLA-981-1.json │ ├── redis.json │ ├── osv-pypi2.json │ ├── CVE-2024-25450.json │ ├── CVE-2022-3567.json │ ├── MAL-2025-6022.json │ ├── CVE-2024-23771.json │ ├── osv_rust_data.json │ ├── CVE-2020-35448.json │ ├── CVE-2022-6083.json │ ├── CVE-2022-32091.json │ ├── CVE-2021-22890.json │ ├── MAL-2024-1396.json │ ├── GO-2022-0251.json │ ├── gha_prob.json │ ├── CVE-2022-3715.json │ ├── MAL-2024-1333.json │ ├── osv-pypi.json │ ├── CVE-2022-3821.json │ ├── GO-2022-0646.json │ ├── osv-maven-single.json │ ├── osv_swift_data.json │ ├── CVE-2019-18625.json │ ├── CVE-2023-52426.json │ ├── CVE-2022-3219.json │ ├── openSUSE-SU-2022-2801-1.json │ ├── osv_mixed_data.json │ ├── RLSA-2022-7730.json │ ├── CVE-2024-3801.json │ ├── osv_swift_data2.json │ ├── osv_mvn_data.json │ ├── RUSTSEC-2024-0343.json │ ├── osv-pypi-django.json │ ├── CVE-2018-9840.json │ ├── osv-pypi4.json │ ├── SUSE-SU-2022-4192-1.json │ ├── osv-pypi-ujson-bug.json │ ├── osv-maven-cvss4.json │ ├── CVE-2021-27434.json │ ├── CVE-2022-21824.json │ ├── GHSA-vc2p-r46x-m3vx.json │ ├── osv-npm-star-bug.json │ ├── CVE-2022-32081.json │ └── ALAS2022-2022-207.json ├── QUERIES.md └── test_npm.py ├── vdb ├── __init__.py └── lib │ ├── orasclient.py │ ├── cve_model │ ├── cvss_v2.py │ ├── tagger.py │ └── cvss_v3.py │ ├── display.py │ ├── custom.py │ └── db6.py ├── contrib ├── cdx-vdb │ ├── pnpm-workspace.yaml │ ├── .gitignore │ ├── README.md │ ├── package.json │ └── index.js ├── Picture1.png ├── Picture2.png ├── Picture3.png ├── Picture4.png ├── Picture5.png ├── Picture6.png ├── deno-vdb │ ├── deno.json │ ├── README.md │ ├── main.ts │ └── deno.lock ├── reporting.md └── cpe_research.py ├── packages └── mcp-server-vdb │ ├── .dockerignore │ ├── docs │ ├── claude-context.png │ ├── latest-malware.png │ ├── vdb-mcp-inspector.png │ ├── vuln-description.png │ └── claude-permissions.png │ ├── .gitignore │ ├── src │ └── mcp_server_vdb │ │ ├── __init__.py │ │ └── display.py │ ├── pyproject.toml │ ├── Dockerfile │ ├── test │ └── test_server.py │ └── README.md ├── docs ├── vdb6.png ├── index-vdb6.png ├── vdb-schema.png └── vdb-index-schema.png ├── .github ├── FUNDING.yml └── workflows │ ├── pythonpublish.yml │ └── pythonapp.yml ├── data ├── imports │ └── cvss │ │ ├── README.md │ │ └── cvss-v2.0.json ├── tags │ ├── adp-tags.json │ ├── cna-tags.json │ └── reference-tags.json └── README.md ├── .flake8 ├── LICENSE ├── pyproject.toml ├── .gitignore └── INTEGRATION.md /test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vdb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contrib/cdx-vdb/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contrib/cdx-vdb/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | -------------------------------------------------------------------------------- /packages/mcp-server-vdb/.dockerignore: -------------------------------------------------------------------------------- 1 | .venv/ 2 | -------------------------------------------------------------------------------- /docs/vdb6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/docs/vdb6.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: prabhu 4 | -------------------------------------------------------------------------------- /contrib/Picture1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture1.png -------------------------------------------------------------------------------- /contrib/Picture2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture2.png -------------------------------------------------------------------------------- /contrib/Picture3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture3.png -------------------------------------------------------------------------------- /contrib/Picture4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture4.png -------------------------------------------------------------------------------- /contrib/Picture5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture5.png -------------------------------------------------------------------------------- /contrib/Picture6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/contrib/Picture6.png -------------------------------------------------------------------------------- /docs/index-vdb6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/docs/index-vdb6.png -------------------------------------------------------------------------------- /docs/vdb-schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/docs/vdb-schema.png -------------------------------------------------------------------------------- /docs/vdb-index-schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/docs/vdb-index-schema.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/docs/claude-context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/packages/mcp-server-vdb/docs/claude-context.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/docs/latest-malware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/packages/mcp-server-vdb/docs/latest-malware.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/docs/vdb-mcp-inspector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/packages/mcp-server-vdb/docs/vdb-mcp-inspector.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/docs/vuln-description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/packages/mcp-server-vdb/docs/vuln-description.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/docs/claude-permissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppThreat/vulnerability-db/HEAD/packages/mcp-server-vdb/docs/claude-permissions.png -------------------------------------------------------------------------------- /packages/mcp-server-vdb/.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | 9 | # Virtual environments 10 | .venv 11 | -------------------------------------------------------------------------------- /contrib/deno-vdb/deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "dev": "deno run --watch main.ts" 4 | }, 5 | "imports": { 6 | "@std/assert": "jsr:@std/assert@1", 7 | "@db/sqlite": "jsr:@db/sqlite@0.12" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /contrib/cdx-vdb/README.md: -------------------------------------------------------------------------------- 1 | # Node.js sample application 2 | 3 | Sample application that use cdxgen with VDB6. 4 | 5 | ```shell 6 | corepack enable pnpm 7 | pnpm install 8 | ``` 9 | 10 | ```shell 11 | node index.js 12 | ``` 13 | -------------------------------------------------------------------------------- /test/data/CVE-2021-3618.json: -------------------------------------------------------------------------------- 1 | { 2 | "os_version": "4.0", 3 | "cve_id": "CVE-2021-3618", 4 | "pkg": "sendmail", 5 | "cve_score": 7.4, 6 | "aff_ver": "all versions before 8.17.1-1.ph4 are vulnerable", 7 | "res_ver": "8.17.1-1.ph4" 8 | } -------------------------------------------------------------------------------- /data/imports/cvss/README.md: -------------------------------------------------------------------------------- 1 | The files in this folder are included here as a stable mirror of the CVSS JSON schemas [maintained](https://www.first.org/cvss/data-representations) by the [Forum of Incident Response and Security Teams](https://www.first.org/) (FIRST). -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E203, E266, E501, W503, W605, C901 3 | max-line-length = 79 4 | max-complexity = 18 5 | select = B,C,E,F,W,T4,B9 6 | exclude = 7 | .venv, 8 | __pycache__, 9 | contrib, 10 | build, 11 | dist, 12 | test 13 | -------------------------------------------------------------------------------- /test/data/CVE-2022-27400.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2022-27400", 4 | "Line": 54533, 5 | "ID": "CVE-2022-27400" 6 | }, 7 | "Annotations": [ 8 | { 9 | "Original": "RESERVED", 10 | "Line": 54534, 11 | "Type": "RESERVED" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /test/data/CVE-2023-21500.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2023-21500", 4 | "Line": 2407, 5 | "ID": "CVE-2023-21500" 6 | }, 7 | "Annotations": [ 8 | { 9 | "Original": "RESERVED", 10 | "Line": 2408, 11 | "Type": "RESERVED" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /packages/mcp-server-vdb/src/mcp_server_vdb/__init__.py: -------------------------------------------------------------------------------- 1 | from . import server 2 | import asyncio 3 | 4 | from contextlib import suppress 5 | 6 | 7 | def main(): 8 | with suppress(asyncio.CancelledError, KeyboardInterrupt): 9 | asyncio.run(server.run()) 10 | 11 | 12 | __all__ = ["main", "server"] 13 | -------------------------------------------------------------------------------- /contrib/deno-vdb/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Mini example to read sqlite data in deno. 4 | 5 | ## Pre-requisites 6 | 7 | ```shell 8 | export VDB_HOME=$HOME/vdb 9 | vdb --download-image 10 | ``` 11 | 12 | ## Usage 13 | 14 | ```shell 15 | deno run --allow-read --allow-write --allow-env --allow-net --allow-ffi main.ts 16 | ``` 17 | -------------------------------------------------------------------------------- /test/data/AVG-999.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AVG-999", 3 | "packages": [ 4 | "irssi" 5 | ], 6 | "status": "Fixed", 7 | "severity": "High", 8 | "type": "arbitrary code execution", 9 | "affected": "1.2.0-4", 10 | "fixed": "1.2.1-1", 11 | "issues": [ 12 | "CVE-2019-13045" 13 | ], 14 | "advisories": [ 15 | "ASA-201907-1" 16 | ] 17 | } -------------------------------------------------------------------------------- /test/data/protobuf-c.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protobuf-c", 3 | "secfixes": { 4 | "1.4.1-r0": [ 5 | "CVE-2022-33070", 6 | "CVE-2021-3121" 7 | ] 8 | }, 9 | "apkurl": "{{urlprefix}}/{{reponame}}/{{arch}}/{{pkg.name}}-{{pkg.ver}}.apk", 10 | "archs": [ 11 | "x86_64" 12 | ], 13 | "urlprefix": "https://packages.wolfi.dev", 14 | "reponame": "os" 15 | } -------------------------------------------------------------------------------- /data/tags/adp-tags.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://cve.mitre.org/cve/v5_00/tags/adp/", 4 | "type": "string", 5 | "description": "disputed: When one party disagrees with another party's assertion that a particular issue in software is a vulnerability, a CVE Record assigned to that issue may be tagged as being 'disputed'.", 6 | "enum": ["disputed"] 7 | } 8 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # Generating cve_model 2 | 3 | Modify the jsonschema to make it compatible with datamodel-code-generator which is quite buggy. 4 | 5 | - Remove $id 6 | - Remove tags: and imports: prefix in $ref 7 | 8 | ```shell 9 | pip install datamodel-code-generator 10 | datamodel-codegen --input data/CVE_Record_Format.json --input-file-type jsonschema --output vdb/lib/cve_model --output-model-type pydantic_v2.BaseModel --target-python-version 3.10 --use-annotated --class-name CVE 11 | ``` 12 | -------------------------------------------------------------------------------- /test/QUERIES.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Collection of SQL queries to test VDB for quality issues. Use with any SQL client. 4 | 5 | ## Queries 6 | 7 | Looking for purl_prefix with any problematic symbols. 8 | 9 | ```sql 10 | select cve_id, purl_prefix from cve_index where purl_prefix like '%)%' or purl_prefix like '%,%' 11 | ``` 12 | 13 | Looking for vers with any problematic symbols. 14 | 15 | ```sql 16 | select cve_id, vers from cve_index where vers like '%)%' or vers like '%,%' 17 | ``` 18 | -------------------------------------------------------------------------------- /contrib/cdx-vdb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdx-vdb", 3 | "version": "1.0.0", 4 | "description": "Sample application that use VDB with cdxgen", 5 | "main": "index.js", 6 | "keywords": [], 7 | "author": "Team AppThreat ", 8 | "type": "module", 9 | "license": "MIT", 10 | "packageManager": "pnpm@10.12.4", 11 | "dependencies": { 12 | "@cyclonedx/cdxgen": "^11.4.3", 13 | "sqlite3": "npm:@appthreat/sqlite3@^6.0.7" 14 | }, 15 | "pnpm": { 16 | "onlyBuiltDependencies": [ 17 | "@appthreat/sqlite3" 18 | ], 19 | "ignoredBuiltDependencies": [ 20 | "sqlite3" 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/data/DLA-981-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "[07 Jun 2017] DLA-981-1 apng2gif - security update", 4 | "Line": 6808, 5 | "ID": "DLA-981-1", 6 | "Description": "apng2gif - security update" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "{CVE-2017-6960}", 11 | "Line": 6809, 12 | "Type": "xref", 13 | "Bugs": [ 14 | "CVE-2017-6960" 15 | ] 16 | }, 17 | { 18 | "Original": "[wheezy] - apng2gif 1.5-1+deb7u1", 19 | "Line": 6810, 20 | "Type": "package", 21 | "Release": "wheezy", 22 | "Package": "apng2gif", 23 | "Kind": "fixed", 24 | "Version": "1.5-1+deb7u1" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /test/data/redis.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redis", 3 | "secfixes": { 4 | "7.0.10-r0": [ 5 | "CVE-2023-28425" 6 | ], 7 | "7.0.11-r0": [ 8 | "CVE-2023-28856" 9 | ], 10 | "7.0.7-r0": [ 11 | "CVE-2022-0543", 12 | "CVE-2022-3734", 13 | "CVE-2022-3647" 14 | ], 15 | "7.0.8-r0": [ 16 | "CVE-2022-35977", 17 | "CVE-2023-22458" 18 | ], 19 | "7.0.9-r0": [ 20 | "CVE-2022-36021", 21 | "CVE-2023-25155" 22 | ] 23 | }, 24 | "apkurl": "{{urlprefix}}/{{reponame}}/{{arch}}/{{pkg.name}}-{{pkg.ver}}.apk", 25 | "archs": [ 26 | "aarch64", 27 | "x86_64" 28 | ], 29 | "urlprefix": "https://packages.cgr.dev", 30 | "reponame": "chainguard" 31 | } -------------------------------------------------------------------------------- /test/data/osv-pypi2.json: -------------------------------------------------------------------------------- 1 | {"id": "PYSEC-2021-349", "details": "XXE vulnerability in XML2Dict version 0.2.2 allows an attacker to cause a denial of service.", "aliases": ["CVE-2021-25951", "GHSA-gp6m-vqhm-5cm5"], "modified": "2021-09-26T23:33:39.694828Z", "published": "2021-06-30T12:15:00Z", "references": [{"type": "WEB", "url": "https://www.whitesourcesoftware.com/vulnerability-database/CVE-2021-25951"}, {"type": "ADVISORY", "url": "https://github.com/advisories/GHSA-gp6m-vqhm-5cm5"}], "affected": [{"package": {"name": "xml2dict", "ecosystem": "PyPI", "purl": "pkg:pypi/xml2dict"}, "ranges": [{"type": "ECOSYSTEM", "events": [{"introduced": "0"}]}], "versions": ["0.1", "0.1.1", "0.2.1", "0.2.2"], "database_specific": {"source": "https://github.com/pypa/advisory-database/blob/main/vulns/xml2dict/PYSEC-2021-349.yaml"}}], "schema_version": "1.4.0"} -------------------------------------------------------------------------------- /test/data/CVE-2024-25450.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "CVE-2024-25450", 3 | "state": [ 4 | { 5 | "fixed": false, 6 | "published": true, 7 | "repo": "3.17-main", 8 | "packageName": "imlib2", 9 | "packageVersion": "1.9.1-r2" 10 | }, 11 | { 12 | "fixed": false, 13 | "published": true, 14 | "repo": "3.10-main", 15 | "packageName": "qemu", 16 | "packageVersion": "4.0.1-r0" 17 | }, 18 | { 19 | "fixed": false, 20 | "published": true, 21 | "repo": "3.13-community", 22 | "packageName": "qemu", 23 | "packageVersion": "5.2.0-r3" 24 | } 25 | ], 26 | "cpeMatch": [ 27 | { 28 | "minimumVersion": "", 29 | "minimumVersionOp": "==", 30 | "maximumVersion": "1.9.1", 31 | "maximumVersionOp": "==" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /vdb/lib/orasclient.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tarfile 3 | 4 | import oras.client 5 | from oras.logger import setup_logger 6 | 7 | setup_logger(quiet=True, debug=False) 8 | 9 | 10 | def download_image(target, outdir): 11 | """ 12 | Method to download vdb files from a oci registry 13 | """ 14 | oras_client = oras.client.OrasClient() 15 | paths_list = oras_client.pull( 16 | target=target, 17 | outdir=outdir, 18 | allowed_media_type=[], 19 | overwrite=True, 20 | ) 21 | for apath in paths_list: 22 | if apath.endswith(".tar.gz") or apath.endswith(".tar.xz"): 23 | with tarfile.open(apath, "r") as tarf: 24 | tarf.extractall(path=outdir) 25 | try: 26 | os.remove(apath) 27 | except OSError: 28 | pass 29 | return paths_list 30 | -------------------------------------------------------------------------------- /test/data/CVE-2022-3567.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2022-3567 (A vulnerability has been found in Linux Kernel and classified as probl ...)", 4 | "Line": 11639, 5 | "ID": "CVE-2022-3567", 6 | "Description": "(A vulnerability has been found in Linux Kernel and classified as probl ...)" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "- linux \u003cunfixed\u003e", 11 | "Line": 11640, 12 | "Type": "package", 13 | "Package": "linux", 14 | "Kind": "unfixed" 15 | }, 16 | { 17 | "Original": "NOTE: https://git.kernel.org/linus/364f997b5cfe1db0d63a390fe7c801fa2b3115f6 (6.1-rc1)", 18 | "Line": 11641, 19 | "Type": "NOTE", 20 | "Description": "https://git.kernel.org/linus/364f997b5cfe1db0d63a390fe7c801fa2b3115f6 (6.1-rc1)" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /data/tags/cna-tags.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://cve.mitre.org/cve/v5_00/tags/cna/", 4 | "type": "string", 5 | "description": "exclusively-hosted-service: All known software and/or hardware affected by this CVE Record is known to exist only in the affected hosted service. If the vulnerability affects both hosted and on-prem software and/or hardware, then the tag should not be used.\n\nunsupported-when-assigned: Used by the assigning CNA to indicate that when a request for a CVE assignment was received, the product was already end-of-life (EOL) or a product or specific version was deemed not to be supported by the vendor. This tag should only be applied to a CVE Record when all affected products or version lines referenced in the CVE-Record are EOL.\n\ndisputed: When one party disagrees with another party's assertion that a particular issue in software is a vulnerability, a CVE Record assigned to that issue may be tagged as being 'disputed'.", 6 | "enum": ["unsupported-when-assigned", "exclusively-hosted-service", "disputed"] 7 | } 8 | -------------------------------------------------------------------------------- /test/data/MAL-2025-6022.json: -------------------------------------------------------------------------------- 1 | { 2 | "modified": "2025-07-21T06:24:05Z", 3 | "published": "2025-07-21T06:24:05Z", 4 | "schema_version": "1.5.0", 5 | "id": "MAL-2025-6022", 6 | "summary": "Malicious code in eslint-config-prettier (npm)", 7 | "details": "This package installs a windows based malware file node-gyp.dll via install.js", 8 | "affected": [ 9 | { 10 | "package": { 11 | "ecosystem": "npm", 12 | "name": "eslint-config-prettier" 13 | }, 14 | "versions": [ 15 | "8.10.1", 16 | "9.1.1", 17 | "10.1.6", 18 | "10.1.7" 19 | ] 20 | } 21 | ], 22 | "references": [ 23 | { 24 | "type": "WEB", 25 | "url": "https://www.bleepingcomputer.com/news/security/popular-npm-linter-packages-hijacked-via-phishing-to-drop-malware/" 26 | } 27 | ], 28 | "credits": [ 29 | { 30 | "name": "GitHax - Software Supply Chain Threat Intelligence", 31 | "type": "FINDER", 32 | "contact": [ 33 | "https://githax.com" 34 | ] 35 | } 36 | ], 37 | "database_specific": { 38 | "malicious-packages-origins": null 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 AppThreat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/data/CVE-2024-23771.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "CVE-2024-23771", 3 | "sourceIdentifier": "cve@mitre.org", 4 | "published": "2024-01-22T04:15:07.723", 5 | "lastModified": "2024-01-22T14:01:09.553", 6 | "vulnStatus": "Awaiting Analysis", 7 | "descriptions": [ 8 | { 9 | "lang": "en", 10 | "value": "darkhttpd before 1.15 uses strcmp (which is not constant time) to verify authentication, which makes it easier for remote attackers to bypass authentication via a timing side channel." 11 | }, 12 | { 13 | "lang": "es", 14 | "value": "darkhttpd anterior a 1.15 usa strcmp (que no es un tiempo constante) para verificar la autenticación, lo que facilita a atacantes remotos eludir la autenticación a través de un canal lateral de temporización." 15 | } 16 | ], 17 | "metrics": {}, 18 | "references": [ 19 | { 20 | "url": "https://github.com/emikulic/darkhttpd/commit/f477619d49f3c4de9ad59bd194265a48ddc03f04", 21 | "source": "cve@mitre.org" 22 | }, 23 | { 24 | "url": "https://github.com/emikulic/darkhttpd/compare/v1.14...v1.15", 25 | "source": "cve@mitre.org" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /contrib/deno-vdb/main.ts: -------------------------------------------------------------------------------- 1 | import { Database } from "@db/sqlite"; 2 | import * as path from "jsr:@std/path"; 3 | 4 | const vdbHome = Deno.env.get("VDB_HOME"); 5 | const indexDBFile = path.join(vdbHome, "data.index.vdb6"); 6 | const cveDBFile = path.join(vdbHome, "data.vdb6"); 7 | 8 | const indexDB = new Database(indexDBFile); 9 | const cveDB = new Database(cveDBFile); 10 | 11 | if (import.meta.main) { 12 | const [indexCount] = indexDB.prepare("SELECT count(*) FROM cve_index").value()!; 13 | const [cveDBCount] = cveDB.prepare("SELECT count(*) FROM cve_data").value()!; 14 | console.log(`Index count: ${indexCount}, VDB count: ${cveDBCount}`); 15 | 16 | console.log("Index Data"); 17 | const rows = indexDB.prepare("SELECT cve_id, type, namespace, name, vers, purl_prefix FROM cve_index LIMIT 10").all(); 18 | for (const row of rows) { 19 | console.log(row); 20 | } 21 | 22 | // Use json(source_data) to read jsonb columns 23 | console.log("CVE Data"); 24 | const vrows = cveDB.prepare("SELECT cve_id, type, namespace, name, json(source_data) as source_data, source_data_hash FROM cve_data LIMIT 10").all(); 25 | for (const row of vrows) { 26 | console.log(row); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/data/osv_rust_data.json: -------------------------------------------------------------------------------- 1 | {"id":"RUSTSEC-2020-0014","summary":"Various memory safety issues","details":"Several memory safety issues have been uncovered in an audit of\nrusqlite.\n\nSee https://github.com/rusqlite/rusqlite/releases/tag/0.23.0 for a complete list.","aliases":["CVE-2020-35866","CVE-2020-35867","CVE-2020-35868","CVE-2020-35869","CVE-2020-35870","CVE-2020-35871","CVE-2020-35872","CVE-2020-35873"],"modified":"2021-01-04T17:02:59Z","published":"2020-04-23T12:00:00Z","references":[{"type":"PACKAGE","url":"https://crates.io/crates/rusqlite"},{"type":"ADVISORY","url":"https://rustsec.org/advisories/RUSTSEC-2020-0014.html"},{"type":"WEB","url":"https://github.com/rusqlite/rusqlite/releases/tag/0.23.0"}],"affected":[{"package":{"name":"rusqlite","ecosystem":"crates.io","purl":"pkg:cargo/rusqlite"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0.0.0-0"},{"fixed":"0.23.0"}]}],"ecosystem_specific":{"affects":{"arch":[],"os":[],"functions":["rusqlite::Connection::get_aux","rusqlite::Connection::set_aux","rusqlite::session::Session::attach","rusqlite::session::Session::diff","rusqlite::trace::log","rusqlite::vtab::create_module"]}},"database_specific":{"categories":[],"informational":null,"source":"https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2020-0014.json","cvss":null}}]} -------------------------------------------------------------------------------- /test/data/CVE-2020-35448.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2020-35448 (An issue was discovered in the Binary File Descriptor (BFD) library (a ...)", 4 | "Line": 147164, 5 | "ID": "CVE-2020-35448", 6 | "Description": "(An issue was discovered in the Binary File Descriptor (BFD) library (a ...)" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "- binutils 2.37-3 (unimportant)", 11 | "Line": 147165, 12 | "Type": "package", 13 | "Package": "binutils", 14 | "Kind": "fixed", 15 | "Version": "2.37-3", 16 | "Severity": "unimportant" 17 | }, 18 | { 19 | "Original": "NOTE: https://sourceware.org/bugzilla/show_bug.cgi?id=26574", 20 | "Line": 147166, 21 | "Type": "NOTE", 22 | "Description": "https://sourceware.org/bugzilla/show_bug.cgi?id=26574" 23 | }, 24 | { 25 | "Original": "NOTE: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8642dafaef21aa6747cec01df1977e9c52eb4679", 26 | "Line": 147167, 27 | "Type": "NOTE", 28 | "Description": "https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8642dafaef21aa6747cec01df1977e9c52eb4679" 29 | }, 30 | { 31 | "Original": "NOTE: binutils not covered by security support", 32 | "Line": 147168, 33 | "Type": "NOTE", 34 | "Description": "binutils not covered by security support" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /test/data/CVE-2022-6083.json: -------------------------------------------------------------------------------- 1 | { 2 | "PublicDateAtUSN": "0001-01-01T00:00:00Z", 3 | "CRD": "0001-01-01T00:00:00Z", 4 | "Candidate": "CVE-2022-6083", 5 | "PublicDate": "2022-08-18T00:00:00Z", 6 | "References": [ 7 | "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-6083", 8 | "https://www.openwall.com/lists/oss-security/2022/08/05/1" 9 | ], 10 | "Description": "[freeciv modpack installer buffer overflow]", 11 | "UbuntuDescription": "", 12 | "Notes": null, 13 | "Bugs": [ 14 | "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1017579" 15 | ], 16 | "Priority": "medium", 17 | "DiscoveredBy": "", 18 | "AssignedTo": "", 19 | "Patches": { 20 | "freeciv": { 21 | "bionic": { 22 | "Status": "needs-triage", 23 | "Note": "" 24 | }, 25 | "devel": { 26 | "Status": "needs-triage", 27 | "Note": "" 28 | }, 29 | "focal": { 30 | "Status": "needs-triage", 31 | "Note": "" 32 | }, 33 | "jammy": { 34 | "Status": "needs-triage", 35 | "Note": "" 36 | }, 37 | "kinetic": { 38 | "Status": "needs-triage", 39 | "Note": "" 40 | }, 41 | "trusty": { 42 | "Status": "ignored", 43 | "Note": "out of standard support" 44 | }, 45 | "upstream": { 46 | "Status": "needs-triage", 47 | "Note": "" 48 | }, 49 | "xenial": { 50 | "Status": "ignored", 51 | "Note": "out of standard support" 52 | } 53 | } 54 | }, 55 | "UpstreamLinks": {} 56 | } -------------------------------------------------------------------------------- /packages/mcp-server-vdb/src/mcp_server_vdb/display.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | from rich.markdown import Markdown 4 | from rich.table import Table 5 | 6 | from vdb.lib.cve_model import CVE 7 | 8 | 9 | def add_table_row(table: Table, res: dict, added_row_keys: dict): 10 | # matched_by is the purl or cpe string 11 | row_key = f"""{res["matched_by"]}|{res.get("source_data_hash")}""" 12 | # Filter duplicate rows from getting printed 13 | if added_row_keys.get(row_key): 14 | return 15 | source_data: CVE = res.get("source_data") 16 | descriptions = [] 17 | cna_container = source_data.root.containers.cna 18 | if cna_container and cna_container.descriptions and cna_container.descriptions.root: 19 | for adesc in cna_container.descriptions.root: 20 | description = ( 21 | "\n".join( 22 | [ 23 | base64.b64decode(sm.value).decode("utf-8") 24 | for sm in adesc.supportingMedia 25 | ] 26 | ) 27 | if adesc.supportingMedia 28 | else adesc.value 29 | ) 30 | description = description.replace("\\n", "\n").replace("\\t", " ") 31 | descriptions.append(description) 32 | table.add_row( 33 | Markdown( 34 | f"[{res.get('cve_id')}](cve://{res.get('cve_id')})", 35 | justify="left", 36 | hyperlinks=True, 37 | ), 38 | res.get("matched_by"), 39 | Markdown("\n".join(descriptions), justify="left", hyperlinks=True), 40 | ) 41 | added_row_keys[row_key] = True 42 | -------------------------------------------------------------------------------- /packages/mcp-server-vdb/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "mcp-server-vdb" 3 | version = "1.1.2" 4 | description = "AppThreat Vulnerability Database MCP server" 5 | authors = [ 6 | {name = "Team AppThreat", email = "cloud@appthreat.com"}, 7 | ] 8 | readme = "README.md" 9 | requires-python = ">=3.10" 10 | license = {text = "MIT"} 11 | classifiers = [ 12 | "Development Status :: 5 - Production/Stable", 13 | "Intended Audience :: Developers", 14 | "Intended Audience :: System Administrators", 15 | "License :: OSI Approved :: MIT License", 16 | "Operating System :: OS Independent", 17 | "Programming Language :: Python :: 3.14", 18 | "Programming Language :: Python :: 3.13", 19 | "Programming Language :: Python :: 3.12", 20 | "Programming Language :: Python :: 3.11", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: Free Threading :: 1 - Unstable", 23 | "Topic :: Security", 24 | "Topic :: Utilities", 25 | ] 26 | 27 | dependencies = [ 28 | "appthreat-vulnerability-db[oras]>=6.5.0", 29 | "mcp[cli]>=1.22.0", 30 | ] 31 | 32 | [build-system] 33 | requires = ["setuptools>=61", "wheel", "build"] 34 | build-backend = "setuptools.build_meta" 35 | 36 | [tool.setuptools] 37 | license-files = [] 38 | 39 | [project.optional-dependencies] 40 | dev = [ 41 | "black", 42 | "bandit", 43 | "flake8", 44 | "pylint", 45 | "pytest", 46 | "pytest-cov", 47 | ] 48 | 49 | [project.scripts] 50 | mcp-server-vdb = "mcp_server_vdb:main" 51 | 52 | [tool.pytest.ini_options] 53 | addopts="--showlocals -v --cov-report=term-missing --no-cov-on-fail --cov vdb" 54 | testpaths = [ 55 | "test" 56 | ] 57 | -------------------------------------------------------------------------------- /test/data/CVE-2022-32091.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2022-32091 (MariaDB v10.7 was discovered to contain an use-after-poison in in __in ...)", 4 | "Line": 42710, 5 | "ID": "CVE-2022-32091", 6 | "Description": "(MariaDB v10.7 was discovered to contain an use-after-poison in in __in ...)" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "{DLA-3114-1}", 11 | "Line": 42711, 12 | "Type": "xref", 13 | "Bugs": [ 14 | "DLA-3114-1" 15 | ] 16 | }, 17 | { 18 | "Original": "- mariadb-10.6 1:10.6.9-1", 19 | "Line": 42712, 20 | "Type": "package", 21 | "Package": "mariadb-10.6", 22 | "Kind": "fixed", 23 | "Version": "1:10.6.9-1" 24 | }, 25 | { 26 | "Original": "- mariadb-10.5 \u003cremoved\u003e", 27 | "Line": 42713, 28 | "Type": "package", 29 | "Package": "mariadb-10.5", 30 | "Kind": "removed" 31 | }, 32 | { 33 | "Original": "[bullseye] - mariadb-10.5 \u003cno-dsa\u003e (Will be fixed via spu)", 34 | "Line": 42714, 35 | "Type": "package", 36 | "Release": "bullseye", 37 | "Package": "mariadb-10.5", 38 | "Kind": "no-dsa", 39 | "Description": "Will be fixed via spu" 40 | }, 41 | { 42 | "Original": "- mariadb-10.3 \u003cremoved\u003e", 43 | "Line": 42715, 44 | "Type": "package", 45 | "Package": "mariadb-10.3", 46 | "Kind": "removed" 47 | }, 48 | { 49 | "Original": "NOTE: https://jira.mariadb.org/browse/MDEV-26431", 50 | "Line": 42716, 51 | "Type": "NOTE", 52 | "Description": "https://jira.mariadb.org/browse/MDEV-26431" 53 | } 54 | ] 55 | } -------------------------------------------------------------------------------- /test/data/CVE-2021-22890.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2021-22890 (curl 7.63.0 to and including 7.75.0 includes vulnerability that allows ...)", 4 | "Line": 135829, 5 | "ID": "CVE-2021-22890", 6 | "Description": "(curl 7.63.0 to and including 7.75.0 includes vulnerability that allows ...)" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "{DSA-4881-1}", 11 | "Line": 135830, 12 | "Type": "xref", 13 | "Bugs": [ 14 | "DSA-4881-1" 15 | ] 16 | }, 17 | { 18 | "Original": "- curl 7.74.0-1.2 (bug #986270)", 19 | "Line": 135831, 20 | "Type": "package", 21 | "Package": "curl", 22 | "Kind": "fixed", 23 | "Version": "7.74.0-1.2", 24 | "BugNo": 986270 25 | }, 26 | { 27 | "Original": "[stretch] - curl \u003cnot-affected\u003e (Vulnerable code introduced later)", 28 | "Line": 135832, 29 | "Type": "package", 30 | "Release": "stretch", 31 | "Package": "curl", 32 | "Kind": "not-affected", 33 | "Description": "Vulnerable code introduced later" 34 | }, 35 | { 36 | "Original": "NOTE: https://curl.se/docs/CVE-2021-22890.html", 37 | "Line": 135833, 38 | "Type": "NOTE", 39 | "Description": "https://curl.se/docs/CVE-2021-22890.html" 40 | }, 41 | { 42 | "Original": "NOTE: Fixed by: https://github.com/curl/curl/commit/b09c8ee15771c614c4bf3ddac893cdb12187c844", 43 | "Line": 135834, 44 | "Type": "NOTE", 45 | "Description": "Fixed by: https://github.com/curl/curl/commit/b09c8ee15771c614c4bf3ddac893cdb12187c844" 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /test/data/MAL-2024-1396.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "MAL-2024-1396", 3 | "summary": "Malicious code in numberpy (PyPI)", 4 | "details": "\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (e10120613afbbf32d487584c68eaf1ae7f4fc0674f1f119d86beae630a3b9070)\nThe OpenSSF Package Analysis project identified 'numberpy' @ 0.1.0 (pypi) as malicious.\n\nIt is considered malicious because:\n\n- The package communicates with a domain associated with malicious activity.\n", 5 | "modified": "2024-05-31T08:26:49Z", 6 | "published": "2024-05-31T08:26:49Z", 7 | "database_specific": { 8 | "malicious-packages-origins": [ 9 | { 10 | "modified_time": "2024-05-31T08:26:49Z", 11 | "import_time": "2024-05-31T08:34:06.567219558Z", 12 | "versions": [ 13 | "0.1.0" 14 | ], 15 | "source": "ossf-package-analysis", 16 | "sha256": "e10120613afbbf32d487584c68eaf1ae7f4fc0674f1f119d86beae630a3b9070" 17 | } 18 | ] 19 | }, 20 | "affected": [ 21 | { 22 | "package": { 23 | "name": "numberpy", 24 | "ecosystem": "PyPI", 25 | "purl": "pkg:pypi/numberpy" 26 | }, 27 | "versions": [ 28 | "0.1.0" 29 | ], 30 | "database_specific": { 31 | "source": "https://github.com/ossf/malicious-packages/blob/main/osv/malicious/pypi/numberpy/MAL-2024-1396.json" 32 | } 33 | } 34 | ], 35 | "schema_version": "1.6.0", 36 | "credits": [ 37 | { 38 | "name": "OpenSSF: Package Analysis", 39 | "contact": [ 40 | "https://github.com/ossf/package-analysis", 41 | "https://openssf.slack.com/channels/package_analysis" 42 | ], 43 | "type": "FINDER" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /test/data/GO-2022-0251.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "GO-2022-0251", 3 | "summary": "Panic on NUL character in ROA in github.com/cloudflare/cfrpki", 4 | "details": "OctoRPKI crashes when a repository returns an invalid ROA that is only an encoded NUL character (\\0).", 5 | "aliases": [ 6 | "CVE-2021-3910" 7 | ], 8 | "modified": "2024-05-20T16:03:47Z", 9 | "published": "2022-07-15T23:07:28Z", 10 | "database_specific": { 11 | "review_status": "REVIEWED", 12 | "url": "https://pkg.go.dev/vuln/GO-2022-0251" 13 | }, 14 | "references": [ 15 | { 16 | "type": "FIX", 17 | "url": "https://github.com/cloudflare/cfrpki/commit/76f0f7a98da001fa04e5bc0407c6702f91096bfa" 18 | } 19 | ], 20 | "affected": [ 21 | { 22 | "package": { 23 | "name": "github.com/cloudflare/cfrpki", 24 | "ecosystem": "Go", 25 | "purl": "pkg:golang/github.com/cloudflare/cfrpki" 26 | }, 27 | "ranges": [ 28 | { 29 | "type": "SEMVER", 30 | "events": [ 31 | { 32 | "introduced": "0" 33 | }, 34 | { 35 | "fixed": "1.4.0" 36 | } 37 | ] 38 | } 39 | ], 40 | "ecosystem_specific": { 41 | "imports": [ 42 | { 43 | "path": "github.com/cloudflare/cfrpki/validator/lib", 44 | "symbols": [ 45 | "BER2DER", 46 | "DecodeManifest", 47 | "DecoderConfig.DecodeManifest", 48 | "readObject" 49 | ] 50 | } 51 | ] 52 | }, 53 | "database_specific": { 54 | "source": "https://vuln.go.dev/ID/GO-2022-0251.json" 55 | } 56 | } 57 | ], 58 | "schema_version": "1.6.0", 59 | "credits": [ 60 | { 61 | "name": "Koen van Hove" 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /test/data/gha_prob.json: -------------------------------------------------------------------------------- 1 | {"cve":{"data_type":"CVE","data_format":"MITRE","data_version":"4.0","CVE_data_meta":{"ID":"CVE-2016-6485","ASSIGNER":"cve@mitre.org"},"problemtype":{"problemtype_data":[{"description":[{"lang":"en","value":"UNKNOWN"}]}]},"references":{"reference_data": [{"url": "https://nvd.nist.gov/vuln/detail/CVE-2016-6485", "name": "https://nvd.nist.gov/vuln/detail/CVE-2016-6485"}, {"url": "https://github.com/advisories/GHSA-h7qw-mxrm-c6h2", "name": "https://github.com/advisories/GHSA-h7qw-mxrm-c6h2"}]},"description":{"description_data":[{"lang":"en","value":"Unauthenticated crypto and weak IV in Magento\Framework\Encryption"}]}},"configurations":{"CVE_data_version":"4.0","nodes":[{"operator":"OR","cpe_match":[{"vulnerable":true,"cpe23Uri":"cpe:2.3:a:magento:community-edition:*:*:*:*:*:*:*:*","versionStartExcluding":"","versionEndExcluding":"2.2.6","versionStartIncluding":"2.0","versionEndIncluding":""}]}]},"impact":{"baseMetricV3":{"cvssV3":{"version":"3.1","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L","attackVector":"NETWORK","attackComplexity":"LOW","privilegesRequired":"NONE","userInteraction":"REQUIRED","scope":"UNCHANGED","confidentialityImpact":"HIGH","integrityImpact":"HIGH","availabilityImpact":"HIGH","baseScore":7.5,"baseSeverity":"HIGH"},"exploitabilityScore":7.5,"impactScore":7.5},"baseMetricV2":{"cvssV2":{"version":"2.0","vectorString":"AV:N/AC:M/Au:N/C:P/I:P/A:P","accessVector":"NETWORK","accessComplexity":"MEDIUM","authentication":"NONE","confidentialityImpact":"PARTIAL","integrityImpact":"PARTIAL","availabilityImpact":"PARTIAL","baseScore":7.5},"severity":"HIGH","exploitabilityScore":7.5,"impactScore":7.5,"acInsufInfo":false,"obtainAllPrivilege":false,"obtainUserPrivilege":false,"obtainOtherPrivilege":false,"userInteractionRequired":false}},"publishedDate":"2019-11-20T01:33:05Z","lastModifiedDate":"2019-11-20T01:33:05Z"} 2 | -------------------------------------------------------------------------------- /test/data/CVE-2022-3715.json: -------------------------------------------------------------------------------- 1 | { 2 | "PublicDateAtUSN": "0001-01-01T00:00:00Z", 3 | "CRD": "0001-01-01T00:00:00Z", 4 | "Candidate": "CVE-2022-3715", 5 | "PublicDate": "2022-11-02T00:00:00Z", 6 | "References": [ 7 | "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-3715", 8 | "https://access.redhat.com/security/cve/CVE-2022-3715" 9 | ], 10 | "Description": "bash: a heap-buffer-overflow in valid_parameter_transform", 11 | "UbuntuDescription": "", 12 | "Notes": [ 13 | "mdeslaur\u003e no details as of 2022-11-03" 14 | ], 15 | "Bugs": null, 16 | "Priority": "medium", 17 | "DiscoveredBy": "", 18 | "AssignedTo": "", 19 | "Patches": { 20 | "bash": { 21 | "bionic": { 22 | "Status": "deferred", 23 | "Note": "2022-11-03" 24 | }, 25 | "devel": { 26 | "Status": "deferred", 27 | "Note": "2022-11-03" 28 | }, 29 | "esm-infra/xenial": { 30 | "Status": "deferred", 31 | "Note": "2022-11-03" 32 | }, 33 | "focal": { 34 | "Status": "deferred", 35 | "Note": "2022-11-03" 36 | }, 37 | "jammy": { 38 | "Status": "deferred", 39 | "Note": "2022-11-03" 40 | }, 41 | "kinetic": { 42 | "Status": "deferred", 43 | "Note": "2022-11-03" 44 | }, 45 | "trusty": { 46 | "Status": "ignored", 47 | "Note": "out of standard support" 48 | }, 49 | "trusty/esm": { 50 | "Status": "deferred", 51 | "Note": "2022-11-03" 52 | }, 53 | "upstream": { 54 | "Status": "needs-triage", 55 | "Note": "" 56 | }, 57 | "xenial": { 58 | "Status": "ignored", 59 | "Note": "out of standard support" 60 | } 61 | } 62 | }, 63 | "UpstreamLinks": {} 64 | } -------------------------------------------------------------------------------- /packages/mcp-server-vdb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv 2 | 3 | # Install the project into `/app` 4 | WORKDIR /app 5 | 6 | # Enable bytecode compilation 7 | ENV UV_COMPILE_BYTECODE=1 8 | 9 | # Copy from the cache instead of linking since it's a mounted volume 10 | ENV UV_LINK_MODE=copy 11 | 12 | # Install the project's dependencies using the lockfile and settings 13 | RUN --mount=type=cache,target=/root/.cache/uv \ 14 | --mount=type=bind,source=uv.lock,target=uv.lock \ 15 | --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ 16 | uv sync --frozen --no-install-project --no-dev --no-editable 17 | 18 | # Then, add the rest of the project source code and install it 19 | # Installing separately from its dependencies allows optimal layer caching 20 | ADD . /app 21 | RUN --mount=type=cache,target=/root/.cache/uv \ 22 | uv sync --frozen --no-dev --no-editable 23 | 24 | FROM python:3.12-slim-bookworm 25 | 26 | LABEL maintainer="Team AppThreat" \ 27 | org.opencontainers.image.authors="Team AppThreat " \ 28 | org.opencontainers.image.source="https://github.com/AppThreat/vulnerability-db" \ 29 | org.opencontainers.image.url="https://github.com/AppThreat/vulnerability-db" \ 30 | org.opencontainers.image.version="1.1.x" \ 31 | org.opencontainers.image.vendor="appthreat" \ 32 | org.opencontainers.image.licenses="MIT" \ 33 | org.opencontainers.image.title="vulnerability-db" \ 34 | org.opencontainers.image.description="MCP server for AppThreat's vulnerability database and package search library." \ 35 | org.opencontainers.docker.cmd="docker run -i --rm -e VDB_HOME=/db -v $HOME/db:/db:rw ghcr.io/appthreat/mcp-server-vdb" 36 | 37 | WORKDIR /app 38 | 39 | COPY --from=uv --chown=app:app /app/.venv /app/.venv 40 | 41 | # This directory must contain the vulnerability database 42 | # export VDB_HOME=/db 43 | # vdb --download-image 44 | ENV PATH="/app/.venv/bin:$PATH" \ 45 | VDB_HOME="/db" 46 | RUN mkdir -p /db && vdb --help 47 | ENTRYPOINT ["mcp-server-vdb"] 48 | -------------------------------------------------------------------------------- /test/data/MAL-2024-1333.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "MAL-2024-1333", 3 | "summary": "Malicious code in threadxpools (PyPI)", 4 | "details": "\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (41a0be6e9aa8db3965bae9f646d47ad6cb85ac9600c8bd71358409062b8fe105)\nThe OpenSSF Package Analysis project identified 'threadxpools' @ 1.2 (pypi) as malicious.\n\nIt is considered malicious because:\n\n- The package communicates with a domain associated with malicious activity.\n", 5 | "modified": "2024-05-06T02:38:12Z", 6 | "published": "2024-05-05T19:10:54Z", 7 | "database_specific": { 8 | "malicious-packages-origins": [ 9 | { 10 | "modified_time": "2024-05-05T19:17:29Z", 11 | "import_time": "2024-05-06T02:37:56.710209536Z", 12 | "versions": [ 13 | "1.2" 14 | ], 15 | "source": "ossf-package-analysis", 16 | "sha256": "41a0be6e9aa8db3965bae9f646d47ad6cb85ac9600c8bd71358409062b8fe105" 17 | }, 18 | { 19 | "modified_time": "2024-05-05T19:10:54Z", 20 | "import_time": "2024-05-06T02:37:56.622833878Z", 21 | "versions": [ 22 | "1.0" 23 | ], 24 | "source": "ossf-package-analysis", 25 | "sha256": "d1017e118ad5a001211a639263fb872dfa5dde20fcd41e1674155a2d7977fb47" 26 | } 27 | ] 28 | }, 29 | "affected": [ 30 | { 31 | "package": { 32 | "name": "threadxpools", 33 | "ecosystem": "PyPI", 34 | "purl": "pkg:pypi/threadxpools" 35 | }, 36 | "versions": [ 37 | "1.2", 38 | "1.0" 39 | ], 40 | "database_specific": { 41 | "source": "https://github.com/ossf/malicious-packages/blob/main/osv/malicious/pypi/threadxpools/MAL-2024-1333.json" 42 | } 43 | } 44 | ], 45 | "schema_version": "1.6.0", 46 | "credits": [ 47 | { 48 | "name": "OpenSSF: Package Analysis", 49 | "contact": [ 50 | "https://github.com/ossf/package-analysis", 51 | "https://openssf.slack.com/channels/package_analysis" 52 | ], 53 | "type": "FINDER" 54 | } 55 | ] 56 | } -------------------------------------------------------------------------------- /test/data/osv-pypi.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.4.0", 3 | "id": "GHSA-gp6m-vqhm-5cm5", 4 | "modified": "2023-09-01T21:41:16Z", 5 | "published": "2021-07-02T18:37:31Z", 6 | "aliases": [ 7 | "CVE-2021-25951" 8 | ], 9 | "summary": "XML2Dict XML Entity Expansion Vulnerability", 10 | "details": "XXE vulnerability in 'XML2Dict' version 0.2.2 allows an attacker to cause a denial of service. The parse function does not properly restrict recursive entity references.", 11 | "severity": [ 12 | { 13 | "type": "CVSS_V3", 14 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" 15 | } 16 | ], 17 | "affected": [ 18 | { 19 | "package": { 20 | "ecosystem": "PyPI", 21 | "name": "XML2Dict" 22 | }, 23 | "ecosystem_specific": { 24 | "affected_functions": [ 25 | "" 26 | ] 27 | }, 28 | "ranges": [ 29 | { 30 | "type": "ECOSYSTEM", 31 | "events": [ 32 | { 33 | "introduced": "0" 34 | }, 35 | { 36 | "last_affected": "0.2.2" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | ], 43 | "references": [ 44 | { 45 | "type": "ADVISORY", 46 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-25951" 47 | }, 48 | { 49 | "type": "WEB", 50 | "url": "https://github.com/mcspring/XML2Dict/tree/master" 51 | }, 52 | { 53 | "type": "WEB", 54 | "url": "https://pypi.org/project/XML2Dict/" 55 | }, 56 | { 57 | "type": "WEB", 58 | "url": "https://www.whitesourcesoftware.com/vulnerability-database/CVE-2021-25951" 59 | } 60 | ], 61 | "database_specific": { 62 | "cwe_ids": [ 63 | "CWE-611", 64 | "CWE-776" 65 | ], 66 | "severity": "HIGH", 67 | "github_reviewed": true, 68 | "github_reviewed_at": "2021-07-01T21:42:31Z", 69 | "nvd_published_at": "2021-06-30T12:15:00Z" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /test/data/CVE-2022-3821.json: -------------------------------------------------------------------------------- 1 | { 2 | "PublicDateAtUSN": "0001-01-01T00:00:00Z", 3 | "CRD": "0001-01-01T00:00:00Z", 4 | "Candidate": "CVE-2022-3821", 5 | "PublicDate": "2022-11-08T22:15:00Z", 6 | "References": [ 7 | "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-3821", 8 | "https://access.redhat.com/security/cve/CVE-2022-3821" 9 | ], 10 | "Description": "An off-by-one Error issue was discovered in Systemd in format_timespan() function of time-util.c. An attacker could supply specific values for time and accuracy that leads to buffer overrun in format_timespan(), leading to a Denial of Service.", 11 | "UbuntuDescription": "", 12 | "Notes": null, 13 | "Bugs": [ 14 | "https://github.com/systemd/systemd/issues/23928", 15 | "https://bugzilla.redhat.com/show_bug.cgi?id=2139327" 16 | ], 17 | "Priority": "medium", 18 | "DiscoveredBy": "", 19 | "AssignedTo": "", 20 | "Patches": { 21 | "systemd": { 22 | "bionic": { 23 | "Status": "needed", 24 | "Note": "" 25 | }, 26 | "devel": { 27 | "Status": "not-affected", 28 | "Note": "251.4-1ubuntu7" 29 | }, 30 | "esm-infra/xenial": { 31 | "Status": "needs-triage", 32 | "Note": "" 33 | }, 34 | "focal": { 35 | "Status": "needed", 36 | "Note": "" 37 | }, 38 | "jammy": { 39 | "Status": "needed", 40 | "Note": "" 41 | }, 42 | "kinetic": { 43 | "Status": "not-affected", 44 | "Note": "251.4-1ubuntu7" 45 | }, 46 | "trusty": { 47 | "Status": "ignored", 48 | "Note": "out of standard support" 49 | }, 50 | "trusty/esm": { 51 | "Status": "needs-triage", 52 | "Note": "" 53 | }, 54 | "upstream": { 55 | "Status": "needs-triage", 56 | "Note": "" 57 | }, 58 | "xenial": { 59 | "Status": "ignored", 60 | "Note": "out of standard support" 61 | } 62 | } 63 | }, 64 | "UpstreamLinks": { 65 | "systemd": [ 66 | "https://github.com/systemd/systemd/commit/9102c625a673a3246d7e73d8737f3494446bad4e" 67 | ] 68 | } 69 | } -------------------------------------------------------------------------------- /test/data/GO-2022-0646.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "GO-2022-0646", 3 | "published": "2022-02-11T23:26:26Z", 4 | "modified": "2022-11-21T19:50:45Z", 5 | "aliases": [ 6 | "CVE-2020-8911", 7 | "CVE-2020-8912" 8 | ], 9 | "details": "The Go AWS S3 Crypto SDK contains vulnerabilities that can permit an attacker with write access to a bucket to decrypt files in that bucket.\n\nFiles encrypted by the V1 EncryptionClient using either the AES-CBC content cipher or the KMS key wrap algorithm are vulnerable. Users should migrate to the V1 EncryptionClientV2 API, which will not create vulnerable files. Old files will remain vulnerable until reencrypted with the new client.", 10 | "affected": [ 11 | { 12 | "package": { 13 | "name": "github.com/aws/aws-sdk-go", 14 | "ecosystem": "Go" 15 | }, 16 | "ranges": [ 17 | { 18 | "type": "SEMVER", 19 | "events": [ 20 | { 21 | "introduced": "0" 22 | } 23 | ] 24 | } 25 | ], 26 | "database_specific": { 27 | "url": "https://pkg.go.dev/vuln/GO-2022-0646" 28 | }, 29 | "ecosystem_specific": { 30 | "imports": [ 31 | { 32 | "path": "github.com/aws/aws-sdk-go/service/s3/s3crypto", 33 | "symbols": [ 34 | "NewDecryptionClient", 35 | "NewEncryptionClient" 36 | ] 37 | } 38 | ] 39 | } 40 | } 41 | ], 42 | "references": [ 43 | { 44 | "type": "ADVISORY", 45 | "url": "https://aws.amazon.com/blogs/developer/updates-to-the-amazon-s3-encryption-client/?s=09" 46 | }, 47 | { 48 | "type": "FIX", 49 | "url": "https://github.com/aws/aws-sdk-go/pull/3403" 50 | }, 51 | { 52 | "type": "FIX", 53 | "url": "https://github.com/aws/aws-sdk-go/commit/ae9b9fd92af132cfd8d879809d8611825ba135f4" 54 | } 55 | ], 56 | "credits": [ 57 | { 58 | "name": "Sophie Schmieg from the Google ISE team" 59 | } 60 | ], 61 | "schema_version": "1.3.1" 62 | } -------------------------------------------------------------------------------- /vdb/lib/cve_model/cvss_v2.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=C0115, C0103, C0301 2 | 3 | from __future__ import annotations 4 | 5 | from enum import Enum 6 | from typing import Annotated, Optional 7 | 8 | from pydantic import BaseModel, Field 9 | 10 | from vdb.lib.cve_model.common import ( 11 | AccessComplexityType, 12 | AccessVectorType, 13 | AuthenticationType, 14 | CiaRequirementType, 15 | CiaTypeModel, 16 | CollateralDamagePotentialType, 17 | ExploitabilityType, 18 | RemediationLevelType, 19 | ReportConfidenceType, 20 | ScoreTypeModel, 21 | TargetDistributionType, 22 | ) 23 | 24 | 25 | class Version(Enum): 26 | field_2_0 = "2.0" 27 | 28 | 29 | class Field0(BaseModel): 30 | version: Annotated[Version, Field(description="CVSS Version")] 31 | vectorString: Annotated[ 32 | str, 33 | Field( 34 | pattern="^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$" 35 | ), 36 | ] 37 | accessVector: Optional[AccessVectorType] = None 38 | accessComplexity: Optional[AccessComplexityType] = None 39 | authentication: Optional[AuthenticationType] = None 40 | confidentialityImpact: Optional[CiaTypeModel] = None 41 | integrityImpact: Optional[CiaTypeModel] = None 42 | availabilityImpact: Optional[CiaTypeModel] = None 43 | baseScore: ScoreTypeModel 44 | exploitability: Optional[ExploitabilityType] = None 45 | remediationLevel: Optional[RemediationLevelType] = None 46 | reportConfidence: Optional[ReportConfidenceType] = None 47 | temporalScore: Optional[ScoreTypeModel] = None 48 | collateralDamagePotential: Optional[CollateralDamagePotentialType] = None 49 | targetDistribution: Optional[TargetDistributionType] = None 50 | confidentialityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 51 | integrityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 52 | availabilityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 53 | environmentalScore: Optional[ScoreTypeModel] = None 54 | -------------------------------------------------------------------------------- /contrib/reporting.md: -------------------------------------------------------------------------------- 1 | # Vulnerability DB Reporting and Metrics 2 | 3 | Loading the populated SQLite vulnerability database into a tool like [qStudio](https://github.com/timeseries/qstudio) can allow for running metrics around specific aspects. The SQLite database can be found in the following location: 4 | - Macintosh: `\Users\\Library\Application Support\vdb\data.vdb` 5 | 6 | The following are some interesting examples and example queries. 7 | 8 | ### Bar Chart for viewing counts of CVE 9 | 10 | Get count of CVE per namespace, for a given year (2018 in this example) 11 | ``` 12 | SELECT namespace AS Namespace, count(namespace) AS Count FROM cve_data WHERE cve_id LIKE "CVE-2018%" AND namespace IS NOT NULL GROUP BY namespace LIMIT 10 13 | ``` 14 | ![image](Picture1.png) 15 | 16 | 17 | Get count of CVE per name, for a given year (2018 in this example) 18 | ``` 19 | SELECT name AS Name, count(name) AS Count FROM cve_data WHERE cve_id LIKE "CVE-2018%" AND name IS NOT NULL GROUP BY name LIMIT 10 20 | ``` 21 | ![image](Picture2.png) 22 | 23 | 24 | Get count of CVE per PURL, for a given year (2018 in this example) 25 | ``` 26 | SELECT purl_prefix AS PURL, count(purl_prefix) AS Count FROM cve_data WHERE cve_id LIKE "CVE-2018%" AND namespace IS NOT NULL GROUP BY purl_prefix LIMIT 10 27 | ``` 28 | ![image](Picture3.png) 29 | 30 | 31 | ### Line Chart for viewing trends of CVE counts per year 32 | 33 | Show trend of CVE count per year, for a given namespace (this example shows namespace of debian) 34 | ``` 35 | SELECT substr(cve_id, 5, 4) AS Year, count(cve_id) AS Count FROM cve_data WHERE namespace = "debian" AND cve_id LIKE "CVE-%" GROUP BY Year 36 | ``` 37 | ![image](Picture4.png) 38 | 39 | 40 | Show trend of CVE count per year, for a given name (this example shows name of .net_core) 41 | ``` 42 | SELECT substr(cve_id, 5, 4) AS Year, count(cve_id) AS Count FROM cve_data WHERE name = ".net_core" AND cve_id LIKE "CVE-%" GROUP BY Year 43 | ``` 44 | ![image](Picture5.png) 45 | 46 | 47 | Show trend of of CVE count per year, for a given PURL (this example shows purl of pkg:alpm/arch/apache) 48 | ``` 49 | SELECT substr(cve_id, 5, 4) AS Year, count(cve_id) AS Count FROM cve_data WHERE purl_prefix = "pkg:alpm/arch/apache" AND cve_id LIKE "CVE-%" GROUP BY Year 50 | ``` 51 | ![image](Picture6.png) 52 | -------------------------------------------------------------------------------- /packages/mcp-server-vdb/test/test_server.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from mcp import ClientSession, StdioServerParameters 4 | from mcp.client.stdio import stdio_client 5 | 6 | # Create server parameters for stdio connection 7 | server_params = StdioServerParameters( 8 | command="uv", 9 | args=["--directory", ".", "run", "mcp-server-vdb"], 10 | env=os.environ 11 | ) 12 | 13 | 14 | async def run(): 15 | async with stdio_client(server_params) as (read, write): 16 | async with ClientSession(read, write) as session: 17 | # Initialize the connection 18 | await session.initialize() 19 | 20 | # List available resources 21 | resources = await session.list_resources() 22 | assert resources 23 | 24 | # Read a resource 25 | content, mime_type = await session.read_resource("cve://CVE-2024-25169") 26 | assert content 27 | 28 | # List available prompts 29 | prompts = await session.list_prompts() 30 | assert prompts 31 | 32 | # Get a prompt 33 | prompt = await session.get_prompt("search-vulnerabilities", arguments={"search": "pkg:pypi/xml2dict@0.2.2"}) 34 | assert prompt 35 | 36 | # List available tools 37 | tools = await session.list_tools() 38 | assert tools 39 | 40 | # Call tools 41 | result = await session.call_tool("search_by_purl_like", arguments={"purl": "pkg:pypi/xml2dict@0.2.2"}) 42 | assert result 43 | result = await session.call_tool("search_by_cpe_like", 44 | arguments={"cpe": "cpe:2.3:a:npm:gitblame:*:*:*:*:*:*:*:*"}) 45 | assert result 46 | result = await session.call_tool("search_by_any", arguments={"search": "npm:gitblame:0.0.1"}) 47 | assert result 48 | result = await session.call_tool("search_by_cve", arguments={"cve_id": "CVE-2024-25169"}) 49 | assert result 50 | result = await session.call_tool("search_by_url", arguments={"url": "https://github.com/electron/electron"}) 51 | assert result 52 | result = await session.call_tool("latest_malware", arguments={"count": 3}) 53 | assert result 54 | 55 | 56 | def test_run(): 57 | import asyncio 58 | 59 | asyncio.run(run()) 60 | -------------------------------------------------------------------------------- /contrib/deno-vdb/deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "specifiers": { 4 | "jsr:@db/sqlite@0.12": "0.12.0", 5 | "jsr:@denosaurs/plug@1": "1.0.6", 6 | "jsr:@std/assert@0.217": "0.217.0", 7 | "jsr:@std/assert@0.221": "0.221.0", 8 | "jsr:@std/encoding@0.221": "0.221.0", 9 | "jsr:@std/fmt@0.221": "0.221.0", 10 | "jsr:@std/fs@0.221": "0.221.0", 11 | "jsr:@std/path@*": "1.0.8", 12 | "jsr:@std/path@0.217": "0.217.0", 13 | "jsr:@std/path@0.221": "0.221.0" 14 | }, 15 | "jsr": { 16 | "@db/sqlite@0.12.0": { 17 | "integrity": "dd1ef7f621ad50fc1e073a1c3609c4470bd51edc0994139c5bf9851de7a6d85f", 18 | "dependencies": [ 19 | "jsr:@denosaurs/plug", 20 | "jsr:@std/path@0.217" 21 | ] 22 | }, 23 | "@denosaurs/plug@1.0.6": { 24 | "integrity": "6cf5b9daba7799837b9ffbe89f3450510f588fafef8115ddab1ff0be9cb7c1a7", 25 | "dependencies": [ 26 | "jsr:@std/encoding", 27 | "jsr:@std/fmt", 28 | "jsr:@std/fs", 29 | "jsr:@std/path@0.221" 30 | ] 31 | }, 32 | "@std/assert@0.217.0": { 33 | "integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642" 34 | }, 35 | "@std/assert@0.221.0": { 36 | "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" 37 | }, 38 | "@std/encoding@0.221.0": { 39 | "integrity": "d1dd76ef0dc5d14088411e6dc1dede53bf8308c95d1537df1214c97137208e45" 40 | }, 41 | "@std/fmt@0.221.0": { 42 | "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" 43 | }, 44 | "@std/fs@0.221.0": { 45 | "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", 46 | "dependencies": [ 47 | "jsr:@std/assert@0.221", 48 | "jsr:@std/path@0.221" 49 | ] 50 | }, 51 | "@std/path@0.217.0": { 52 | "integrity": "1217cc25534bca9a2f672d7fe7c6f356e4027df400c0e85c0ef3e4343bc67d11", 53 | "dependencies": [ 54 | "jsr:@std/assert@0.217" 55 | ] 56 | }, 57 | "@std/path@0.221.0": { 58 | "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", 59 | "dependencies": [ 60 | "jsr:@std/assert@0.221" 61 | ] 62 | }, 63 | "@std/path@1.0.8": { 64 | "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" 65 | } 66 | }, 67 | "workspace": { 68 | "dependencies": [ 69 | "jsr:@db/sqlite@0.12", 70 | "jsr:@std/assert@1" 71 | ] 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "appthreat-vulnerability-db" 3 | version = "6.6.0" 4 | description = "AppThreat's vulnerability database and package search library with a built-in sqlite based storage. OSV, CVE, GitHub, npm are the primary sources of vulnerabilities." 5 | authors = [ 6 | {name = "Team AppThreat", email = "cloud@appthreat.com"}, 7 | ] 8 | dependencies = [ 9 | "httpx[http2]", 10 | "appdirs", 11 | "orjson", 12 | "semver", 13 | "packageurl-python", 14 | "cvss", 15 | "pydantic[email]", 16 | "rich", 17 | "apsw" 18 | ] 19 | requires-python = ">=3.10" 20 | readme = "README.md" 21 | license = {text = "MIT"} 22 | classifiers = [ 23 | "Development Status :: 5 - Production/Stable", 24 | "Intended Audience :: Developers", 25 | "Intended Audience :: System Administrators", 26 | "License :: OSI Approved :: MIT License", 27 | "Operating System :: OS Independent", 28 | "Programming Language :: Python :: 3.14", 29 | "Programming Language :: Python :: 3.13", 30 | "Programming Language :: Python :: 3.12", 31 | "Programming Language :: Python :: 3.11", 32 | "Programming Language :: Python :: 3.10", 33 | "Programming Language :: Python :: Free Threading :: 1 - Unstable", 34 | "Topic :: Security", 35 | "Topic :: Utilities", 36 | ] 37 | 38 | [project.urls] 39 | Homepage = "https://github.com/appthreat/vulnerability-db" 40 | 41 | [project.scripts] 42 | vdb = "vdb.cli:main" 43 | 44 | [build-system] 45 | requires = ["setuptools>=61", "wheel", "build"] 46 | build-backend = "setuptools.build_meta" 47 | 48 | [project.optional-dependencies] 49 | dev = [ 50 | "black", 51 | "bandit", 52 | "flake8", 53 | "pylint", 54 | "pytest", 55 | "pytest-cov", 56 | ] 57 | custom = ["PyYAML", "tomli; python_version < '3.11'"] 58 | oras = ["oras>=0.2.25"] 59 | all = ["oras>=0.2.25", "PyYAML", "tomli; python_version < '3.11'"] 60 | 61 | [tool.setuptools] 62 | packages = ["vdb", "vdb.lib", "vdb.lib.cve_model"] 63 | license-files = [] 64 | 65 | [tool.pytest.ini_options] 66 | addopts="--showlocals -v --cov-report=term-missing --no-cov-on-fail --cov vdb" 67 | testpaths = [ 68 | "test" 69 | ] 70 | 71 | [tool.pylint] 72 | disable = ["broad-exception-caught", "too-many-branches", "too-many-statements", "too-many-nested-blocks", "too-many-locals", "missing-function-docstring", "too-many-lines", "missing-module-docstring"] 73 | ignore-paths = ["vdb/lib/cve_model/*"] 74 | generated-member = ["orjson.loads", "orjson.dumps", "orjson.OPT_NAIVE_UTC"] 75 | 76 | [dependency-groups] 77 | dev = [ 78 | "ruff>=0.11.7", 79 | ] 80 | -------------------------------------------------------------------------------- /vdb/lib/display.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | from rich.markdown import Markdown 4 | from rich.table import Table 5 | 6 | from vdb.lib.cve_model import CVE 7 | 8 | NEWLINE = "\n" 9 | 10 | 11 | def add_table_row(table: Table, res: dict, added_row_keys: dict): 12 | # matched_by is the purl or cpe string 13 | row_key = f"""{res["matched_by"]}|{res.get("source_data_hash")}""" 14 | # Filter duplicate rows from getting printed 15 | if added_row_keys.get(row_key): 16 | return 17 | source_data: CVE = res.get("source_data") 18 | fix_version = res.get("fix_version", "") 19 | descriptions = [] 20 | cna_container = source_data.root.containers.cna 21 | affected_functions = set() 22 | affected_modules = set() 23 | if cna_container and cna_container.descriptions and cna_container.descriptions.root: 24 | for adesc in cna_container.descriptions.root: 25 | description = ( 26 | "\n".join( 27 | [ 28 | base64.b64decode(sm.value).decode("utf-8") 29 | for sm in adesc.supportingMedia 30 | ] 31 | ) 32 | if adesc.supportingMedia 33 | else adesc.value 34 | ) 35 | description = description.replace("\\n", "\n").replace("\\t", " ") 36 | descriptions.append(description) 37 | if cna_container.affected and cna_container.affected.root: 38 | for each_affected in cna_container.affected.root: 39 | if each_affected.programRoutines: 40 | affected_functions |= {r.name for r in each_affected.programRoutines} 41 | if each_affected.modules: 42 | affected_modules |= {m.root for m in each_affected.modules} 43 | affected_functions = list(affected_functions) 44 | affected_modules = list(affected_modules) 45 | affects = "" 46 | if affected_functions: 47 | affects = f"## Functions\n- {(NEWLINE + '- ').join(affected_functions)}" 48 | if affected_modules: 49 | affects = f"{affects}\n## Modules\n- {(NEWLINE + '- ').join(affected_modules)}" 50 | matched_by_str = ( 51 | f"{res['matched_by']}\n{res.get('purl_prefix')}" 52 | if not res["matched_by"].startswith("pkg:") 53 | else res["matched_by"] 54 | ) 55 | table.add_row( 56 | res.get("cve_id"), 57 | matched_by_str, 58 | fix_version, 59 | Markdown("\n".join(descriptions), justify="left", hyperlinks=True), 60 | Markdown(affects, justify="left"), 61 | ) 62 | added_row_keys[row_key] = True 63 | -------------------------------------------------------------------------------- /test/data/osv-maven-single.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.4.0", 3 | "id": "GHSA-r4q3-7g4q-x89m", 4 | "modified": "2024-06-17T17:18:05Z", 5 | "published": "2024-01-22T15:30:23Z", 6 | "aliases": [ 7 | "CVE-2024-22233" 8 | ], 9 | "summary": "Spring Framework server Web DoS Vulnerability", 10 | "details": "In Spring Framework versions 6.0.15 and 6.1.2, it is possible for a user to provide specially crafted HTTP requests that may cause a denial-of-service (DoS) condition.\n\nSpecifically, an application is vulnerable when all of the following are true:\n\n * the application uses Spring MVC\n * Spring Security 6.1.6+ or 6.2.1+ is on the classpath\n\n\nTypically, Spring Boot applications need the org.springframework.boot:spring-boot-starter-web and org.springframework.boot:spring-boot-starter-security dependencies to meet all conditions.\n\n\n", 11 | "severity": [ 12 | { 13 | "type": "CVSS_V3", 14 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" 15 | } 16 | ], 17 | "affected": [ 18 | { 19 | "package": { 20 | "ecosystem": "Maven", 21 | "name": "org.springframework:spring-core" 22 | }, 23 | "ranges": [ 24 | { 25 | "type": "ECOSYSTEM", 26 | "events": [ 27 | { 28 | "introduced": "6.1.2" 29 | }, 30 | { 31 | "fixed": "6.1.3" 32 | } 33 | ] 34 | } 35 | ], 36 | "versions": [ 37 | "6.1.2" 38 | ] 39 | }, 40 | { 41 | "package": { 42 | "ecosystem": "Maven", 43 | "name": "org.springframework:spring-core" 44 | }, 45 | "ranges": [ 46 | { 47 | "type": "ECOSYSTEM", 48 | "events": [ 49 | { 50 | "introduced": "6.0.15" 51 | }, 52 | { 53 | "fixed": "6.0.16" 54 | } 55 | ] 56 | } 57 | ], 58 | "versions": [ 59 | "6.0.15" 60 | ] 61 | } 62 | ], 63 | "references": [ 64 | { 65 | "type": "ADVISORY", 66 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-22233" 67 | }, 68 | { 69 | "type": "WEB", 70 | "url": "https://security.netapp.com/advisory/ntap-20240614-0005" 71 | }, 72 | { 73 | "type": "WEB", 74 | "url": "https://spring.io/security/cve-2024-22233" 75 | } 76 | ], 77 | "database_specific": { 78 | "cwe_ids": [ 79 | 80 | ], 81 | "severity": "HIGH", 82 | "github_reviewed": true, 83 | "github_reviewed_at": "2024-01-23T14:44:07Z", 84 | "nvd_published_at": "2024-01-22T13:15:25Z" 85 | } 86 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_STORE 2 | .idea/ 3 | .gitleaks_bin/ 4 | repos/ 5 | .vscode/ 6 | .tox/ 7 | .tool-versions 8 | venv/ 9 | # Byte-compiled / optimized / DLL files 10 | __pycache__/ 11 | *.py[cod] 12 | *$py.class 13 | 14 | # C extensions 15 | *.so 16 | 17 | # Distribution / packaging 18 | .Python 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | wheels/ 30 | pip-wheel-metadata/ 31 | share/python-wheels/ 32 | *.egg-info/ 33 | .installed.cfg 34 | *.egg 35 | MANIFEST 36 | 37 | # PyInstaller 38 | # Usually these files are written by a python script from a template 39 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 40 | *.manifest 41 | *.spec 42 | 43 | # Installer logs 44 | pip-log.txt 45 | pip-delete-this-directory.txt 46 | 47 | # Unit test / coverage reports 48 | htmlcov/ 49 | .tox/ 50 | .nox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *.cover 57 | *.py,cover 58 | .hypothesis/ 59 | .pytest_cache/ 60 | 61 | # Translations 62 | *.mo 63 | *.pot 64 | 65 | # Django stuff: 66 | *.log 67 | local_settings.py 68 | db.sqlite3 69 | db.sqlite3-journal 70 | 71 | # Flask stuff: 72 | instance/ 73 | .webassets-cache 74 | 75 | # Scrapy stuff: 76 | .scrapy 77 | 78 | # Sphinx documentation 79 | docs/_build/ 80 | 81 | # PyBuilder 82 | target/ 83 | 84 | # Jupyter Notebook 85 | .ipynb_checkpoints 86 | 87 | # IPython 88 | profile_default/ 89 | ipython_config.py 90 | 91 | # pyenv 92 | .python-version 93 | 94 | # pipenv 95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 98 | # install all needed dependencies. 99 | #Pipfile.lock 100 | 101 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 102 | __pypackages__/ 103 | 104 | # Celery stuff 105 | celerybeat-schedule 106 | celerybeat.pid 107 | 108 | # SageMath parsed files 109 | *.sage.py 110 | 111 | # Environments 112 | .env 113 | .venv 114 | env/ 115 | venv/ 116 | ENV/ 117 | env.bak/ 118 | venv.bak/ 119 | 120 | # Spyder project settings 121 | .spyderproject 122 | .spyproject 123 | 124 | # Rope project settings 125 | .ropeproject 126 | 127 | # mkdocs documentation 128 | /site 129 | 130 | # mypy 131 | .mypy_cache/ 132 | .dmypy.json 133 | dmypy.json 134 | 135 | # Pyre type checker 136 | .pyre/ 137 | .coverage 138 | reports/ 139 | .mise.toml 140 | out.txt 141 | bom.json 142 | -------------------------------------------------------------------------------- /test/data/osv_swift_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "GHSA-vcvg-xgr8-p5gq", 3 | "summary": "Arbitrary file read using percent-encoded relative paths in FileMiddleware", 4 | "details": "### Impact\n\nAttackers can access data at arbitrary filesystem paths on the same host as an application using `FileMiddleware`.\n\n### Patches\n\nVersion [4.29.4](https://github.com/vapor/vapor/releases/tag/4.29.4)\n\n### Workarounds\n\nUpgrade to 4.24.4 or later, or disable `FileMiddleware`.\n\n### References\n\n* Introduced in https://github.com/vapor/vapor/pull/2223\n* Fixed by https://github.com/vapor/vapor/pull/2500\n\n### For more information\n\nIf you have any questions or comments about this advisory:\n* Open [an issue](https://github.com/vapor/vapor/issues)\n* Email us at [security@vapor.codes](mailto:security@vapor.codes)", 5 | "aliases": [ 6 | "CVE-2020-15230" 7 | ], 8 | "modified": "2023-11-08T04:02:34.559462Z", 9 | "published": "2023-06-09T19:31:32Z", 10 | "database_specific": { 11 | "nvd_published_at": "2020-10-02T19:15:00Z", 12 | "cwe_ids": [ 13 | "CWE-22" 14 | ], 15 | "severity": "MODERATE", 16 | "github_reviewed": true, 17 | "github_reviewed_at": "2023-06-09T19:31:32Z" 18 | }, 19 | "references": [ 20 | { 21 | "type": "WEB", 22 | "url": "https://github.com/vapor/vapor/security/advisories/GHSA-vcvg-xgr8-p5gq" 23 | }, 24 | { 25 | "type": "ADVISORY", 26 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-15230" 27 | }, 28 | { 29 | "type": "WEB", 30 | "url": "https://github.com/vapor/vapor/pull/2500" 31 | }, 32 | { 33 | "type": "WEB", 34 | "url": "https://github.com/vapor/vapor/commit/cf1651f7ff76515593f4d8ca6e6e15d2247fe255" 35 | }, 36 | { 37 | "type": "PACKAGE", 38 | "url": "https://github.com/vapor/vapor" 39 | } 40 | ], 41 | "affected": [ 42 | { 43 | "package": { 44 | "name": "github.com/vapor/vapor", 45 | "ecosystem": "SwiftURL" 46 | }, 47 | "ranges": [ 48 | { 49 | "type": "SEMVER", 50 | "events": [ 51 | { 52 | "introduced": "4.0.0-rc.2.5" 53 | }, 54 | { 55 | "fixed": "4.29.4" 56 | } 57 | ] 58 | } 59 | ], 60 | "database_specific": { 61 | "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2023/06/GHSA-vcvg-xgr8-p5gq/GHSA-vcvg-xgr8-p5gq.json" 62 | } 63 | } 64 | ], 65 | "schema_version": "1.6.0", 66 | "severity": [ 67 | { 68 | "type": "CVSS_V3", 69 | "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N" 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /test/data/CVE-2019-18625.json: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Original": "CVE-2019-18625 (An issue was discovered in Suricata 5.0.0. It was possible to bypass/e ...)", 4 | "Line": 226679, 5 | "ID": "CVE-2019-18625", 6 | "Description": "(An issue was discovered in Suricata 5.0.0. It was possible to bypass/e ...)" 7 | }, 8 | "Annotations": [ 9 | { 10 | "Original": "{DLA-2087-1}", 11 | "Line": 226680, 12 | "Type": "xref", 13 | "Bugs": [ 14 | "DLA-2087-1" 15 | ] 16 | }, 17 | { 18 | "Original": "[experimental] - suricata 1:5.0.1-1~exp1", 19 | "Line": 226681, 20 | "Type": "package", 21 | "Release": "experimental", 22 | "Package": "suricata", 23 | "Kind": "fixed", 24 | "Version": "1:5.0.1-1~exp1" 25 | }, 26 | { 27 | "Original": "- suricata 1:5.0.2-1", 28 | "Line": 226682, 29 | "Type": "package", 30 | "Package": "suricata", 31 | "Kind": "fixed", 32 | "Version": "1:5.0.2-1" 33 | }, 34 | { 35 | "Original": "[buster] - suricata \u003cno-dsa\u003e (Minor issue)", 36 | "Line": 226683, 37 | "Type": "package", 38 | "Release": "buster", 39 | "Package": "suricata", 40 | "Kind": "no-dsa", 41 | "Description": "Minor issue" 42 | }, 43 | { 44 | "Original": "[stretch] - suricata \u003cno-dsa\u003e (Minor issue)", 45 | "Line": 226684, 46 | "Type": "package", 47 | "Release": "stretch", 48 | "Package": "suricata", 49 | "Kind": "no-dsa", 50 | "Description": "Minor issue" 51 | }, 52 | { 53 | "Original": "NOTE: https://github.com/OISF/suricata/commit/9f0294fadca3dcc18c919424242a41e01f3e8318 (suricata-5.0.1)", 54 | "Line": 226685, 55 | "Type": "NOTE", 56 | "Description": "https://github.com/OISF/suricata/commit/9f0294fadca3dcc18c919424242a41e01f3e8318 (suricata-5.0.1)" 57 | }, 58 | { 59 | "Original": "NOTE: https://github.com/OISF/suricata/commit/ea0659de7640cf6a51de5bbd1dbbb0414e4623a0 (master-4.1.x)", 60 | "Line": 226686, 61 | "Type": "NOTE", 62 | "Description": "https://github.com/OISF/suricata/commit/ea0659de7640cf6a51de5bbd1dbbb0414e4623a0 (master-4.1.x)" 63 | }, 64 | { 65 | "Original": "NOTE: https://redmine.openinfosecfoundation.org/issues/3286", 66 | "Line": 226687, 67 | "Type": "NOTE", 68 | "Description": "https://redmine.openinfosecfoundation.org/issues/3286" 69 | }, 70 | { 71 | "Original": "NOTE: https://redmine.openinfosecfoundation.org/issues/3395", 72 | "Line": 226688, 73 | "Type": "NOTE", 74 | "Description": "https://redmine.openinfosecfoundation.org/issues/3395" 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /test/data/CVE-2023-52426.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "CVE-2023-52426", 3 | "sourceIdentifier": "cve@mitre.org", 4 | "published": "2024-02-04T20:15:46.120", 5 | "lastModified": "2024-02-09T02:02:39.800", 6 | "vulnStatus": "Analyzed", 7 | "descriptions": [ 8 | { 9 | "lang": "en", 10 | "value": "libexpat through 2.5.0 allows recursive XML Entity Expansion if XML_DTD is undefined at compile time." 11 | }, 12 | { 13 | "lang": "es", 14 | "value": "libexpat hasta 2.5.0 permite la expansión recursiva de entidades XML si XML_DTD no está definido en el momento de la compilación." 15 | } 16 | ], 17 | "metrics": { 18 | "cvssMetricV31": [ 19 | { 20 | "source": "nvd@nist.gov", 21 | "type": "Primary", 22 | "cvssData": { 23 | "version": "3.1", 24 | "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", 25 | "attackVector": "LOCAL", 26 | "attackComplexity": "LOW", 27 | "privilegesRequired": "LOW", 28 | "userInteraction": "NONE", 29 | "scope": "UNCHANGED", 30 | "confidentialityImpact": "NONE", 31 | "integrityImpact": "NONE", 32 | "availabilityImpact": "HIGH", 33 | "baseScore": 5.5, 34 | "baseSeverity": "MEDIUM" 35 | }, 36 | "exploitabilityScore": 1.8, 37 | "impactScore": 3.6 38 | } 39 | ] 40 | }, 41 | "weaknesses": [ 42 | { 43 | "source": "nvd@nist.gov", 44 | "type": "Primary", 45 | "description": [ 46 | { 47 | "lang": "en", 48 | "value": "CWE-776" 49 | } 50 | ] 51 | } 52 | ], 53 | "configurations": [ 54 | { 55 | "nodes": [ 56 | { 57 | "operator": "OR", 58 | "negate": false, 59 | "cpeMatch": [ 60 | { 61 | "vulnerable": true, 62 | "criteria": "cpe:2.3:a:libexpat_project:libexpat:*:*:*:*:*:*:*:*", 63 | "matchCriteriaId": "1C50909D-8A18-484B-A7DB-7EF4CA67C2CB", 64 | "versionEndIncluding": "2.5.0" 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ], 71 | "references": [ 72 | { 73 | "url": "https://cwe.mitre.org/data/definitions/776.html", 74 | "source": "cve@mitre.org", 75 | "tags": [ 76 | "Technical Description" 77 | ] 78 | }, 79 | { 80 | "url": "https://github.com/libexpat/libexpat/commit/0f075ec8ecb5e43f8fdca5182f8cca4703da0404", 81 | "source": "cve@mitre.org", 82 | "tags": [ 83 | "Patch", 84 | "Vendor Advisory" 85 | ] 86 | }, 87 | { 88 | "url": "https://github.com/libexpat/libexpat/pull/777", 89 | "source": "cve@mitre.org", 90 | "tags": [ 91 | "Vendor Advisory" 92 | ] 93 | } 94 | ] 95 | } -------------------------------------------------------------------------------- /contrib/cdx-vdb/index.js: -------------------------------------------------------------------------------- 1 | import { createNodejsBom } from "@cyclonedx/cdxgen"; 2 | import { dirname, join } from "node:path"; 3 | import { URL, fileURLToPath } from "node:url"; 4 | import SQLite from "sqlite3"; 5 | import { promisify } from "util"; 6 | 7 | let url = import.meta?.url; 8 | if (url && !url.startsWith("file://")) { 9 | url = new URL(`file://${import.meta.url}`).toString(); 10 | } 11 | 12 | // Current directory 13 | export const dirNameStr = url ? dirname(fileURLToPath(url)) : __dirname; 14 | 15 | const vdbHome = process.env.VDB_HOME; 16 | const indexDBFile = join(vdbHome, "data.index.vdb6"); 17 | const cveDBFile = join(vdbHome, "data.vdb6"); 18 | const indexDB = new SQLite.Database(indexDBFile, (err) => { 19 | if (err) { 20 | console.error("Failed to open indexDB:", err); 21 | } 22 | }); 23 | const cveDB = new SQLite.Database(cveDBFile, (err) => { 24 | if (err) { 25 | console.error("Failed to open cveDB:", err); 26 | } 27 | }); 28 | const indexAllAsync = promisify(indexDB.all.bind(indexDB)); 29 | 30 | // Print counts 31 | indexDB.get("SELECT COUNT(*) AS count FROM cve_index", (err, row) => { 32 | if (err) { 33 | console.error("Error querying index count:", err); 34 | } else { 35 | console.log(`Index count: ${row.count}`); 36 | } 37 | }); 38 | 39 | cveDB.get("SELECT COUNT(*) AS count FROM cve_data", (err, row) => { 40 | if (err) { 41 | console.error("Error querying VDB count:", err); 42 | } else { 43 | console.log(`VDB count: ${row.count}`); 44 | } 45 | }); 46 | 47 | // Print some rows 48 | console.log("Some Index Data"); 49 | indexDB.each( 50 | "SELECT cve_id, type, namespace, name, vers, purl_prefix FROM cve_index LIMIT 10", 51 | (err, row) => { 52 | console.log(row); 53 | } 54 | ); 55 | 56 | console.log("Some CVE Data"); 57 | cveDB.each( 58 | "SELECT cve_id, type, namespace, name, json(source_data) as source_data, source_data_hash FROM cve_data LIMIT 10", 59 | (err, row) => { 60 | console.log(row); 61 | } 62 | ); 63 | 64 | const bomNSData = await createNodejsBom(dirNameStr, { 65 | recurse: false, 66 | projectType: ["pnpm"] 67 | }); 68 | 69 | const components = bomNSData?.bomJson?.components || []; 70 | 71 | // Check the local sbom for vulns 72 | for (const comp of components) { 73 | console.log("Checking", comp.purl); 74 | try { 75 | const rows = await indexAllAsync( 76 | "SELECT cve_id, type, namespace, name, vers, purl_prefix FROM cve_index WHERE purl_prefix = ?", 77 | [comp.purl] 78 | ); 79 | for (const row of rows) { 80 | console.log(row); 81 | } 82 | } catch (err) { 83 | console.error("Query error for", comp.purl, err); 84 | } 85 | } 86 | 87 | indexDB.close((err) => { 88 | if (err) console.error("Error closing indexDB:", err); 89 | }); 90 | cveDB.close((err) => { 91 | if (err) console.error("Error closing cveDB:", err); 92 | }); 93 | -------------------------------------------------------------------------------- /test/data/CVE-2022-3219.json: -------------------------------------------------------------------------------- 1 | { 2 | "PublicDateAtUSN": "0001-01-01T00:00:00Z", 3 | "CRD": "0001-01-01T00:00:00Z", 4 | "Candidate": "CVE-2022-3219", 5 | "PublicDate": "2022-09-28T00:00:00Z", 6 | "References": [ 7 | "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-3219", 8 | "https://access.redhat.com/security/cve/CVE-2022-3219", 9 | "https://marc.info/?l=oss-security\u0026m=165696590211434\u0026w=4" 10 | ], 11 | "Description": "gnupg: denial of service issue (resource consumption) using compressed packets", 12 | "UbuntuDescription": "", 13 | "Notes": [ 14 | "mdeslaur\u003e per the upstream gnupg bug, the change will not be applied", 15 | "mdeslaur\u003e as of 2022-09-28, proposed patch has not been accepted by", 16 | "mdeslaur\u003e upstream developers" 17 | ], 18 | "Bugs": [ 19 | "https://dev.gnupg.org/T5993" 20 | ], 21 | "Priority": "low", 22 | "DiscoveredBy": "", 23 | "AssignedTo": "", 24 | "Patches": { 25 | "gnupg": { 26 | "bionic": { 27 | "Status": "DNE", 28 | "Note": "" 29 | }, 30 | "esm-infra/xenial": { 31 | "Status": "deferred", 32 | "Note": "2022-09-28" 33 | }, 34 | "focal": { 35 | "Status": "DNE", 36 | "Note": "" 37 | }, 38 | "jammy": { 39 | "Status": "DNE", 40 | "Note": "" 41 | }, 42 | "trusty": { 43 | "Status": "ignored", 44 | "Note": "out of standard support" 45 | }, 46 | "trusty/esm": { 47 | "Status": "deferred", 48 | "Note": "2022-09-28" 49 | }, 50 | "upstream": { 51 | "Status": "needs-triage", 52 | "Note": "" 53 | }, 54 | "xenial": { 55 | "Status": "ignored", 56 | "Note": "out of standard support" 57 | } 58 | }, 59 | "gnupg2": { 60 | "bionic": { 61 | "Status": "deferred", 62 | "Note": "2022-09-28" 63 | }, 64 | "devel": { 65 | "Status": "deferred", 66 | "Note": "2022-09-28" 67 | }, 68 | "esm-infra/xenial": { 69 | "Status": "deferred", 70 | "Note": "2022-09-28" 71 | }, 72 | "focal": { 73 | "Status": "deferred", 74 | "Note": "2022-09-28" 75 | }, 76 | "jammy": { 77 | "Status": "deferred", 78 | "Note": "2022-09-28" 79 | }, 80 | "kinetic": { 81 | "Status": "deferred", 82 | "Note": "2022-09-28" 83 | }, 84 | "trusty": { 85 | "Status": "ignored", 86 | "Note": "out of standard support" 87 | }, 88 | "upstream": { 89 | "Status": "needs-triage", 90 | "Note": "" 91 | }, 92 | "xenial": { 93 | "Status": "ignored", 94 | "Note": "end of standard support" 95 | } 96 | } 97 | }, 98 | "UpstreamLinks": {} 99 | } -------------------------------------------------------------------------------- /test/data/openSUSE-SU-2022-2801-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "Title": "Security update for cifs-utils", 3 | "Tracking": { 4 | "ID": "openSUSE-SU-2022:2801-1", 5 | "Status": "Final", 6 | "Version": "1", 7 | "InitialReleaseDate": "2022-08-12T14:28:36Z", 8 | "CurrentReleaseDate": "2022-08-12T14:28:36Z", 9 | "RevisionHistory": [ 10 | { 11 | "Number": "1", 12 | "Date": "2022-08-12T14:28:36Z", 13 | "Description": "current" 14 | } 15 | ] 16 | }, 17 | "Notes": [ 18 | { 19 | "Text": "Security update for cifs-utils", 20 | "Title": "Topic", 21 | "Type": "Summary" 22 | }, 23 | { 24 | "Text": "This update for cifs-utils fixes the following issues:\n\n- CVE-2022-29869: Fixed verbose messages on option parsing causing information leak (bsc#1198976).\n", 25 | "Title": "Details", 26 | "Type": "General" 27 | }, 28 | { 29 | "Text": "The CVRF data is provided by SUSE under the Creative Commons License 4.0 with Attribution (CC-BY-4.0).", 30 | "Title": "Terms of Use", 31 | "Type": "Legal Disclaimer" 32 | } 33 | ], 34 | "ProductTree": { 35 | "Relationships": [ 36 | { 37 | "ProductReference": "cifs-utils-6.9-150100.5.18.1", 38 | "RelatesToProductReference": "openSUSE Leap Micro 5.2", 39 | "RelationType": "Default Component Of" 40 | } 41 | ] 42 | }, 43 | "References": [ 44 | { 45 | "URL": "https://lists.opensuse.org/archives/list/security-announce@lists.opensuse.org/thread/744TDSJVWGHR6LCEL64KSZ6F4ZOIZJQP/", 46 | "Description": "E-Mail link for openSUSE-SU-2022:2801-1" 47 | }, 48 | { 49 | "URL": "https://www.suse.com/support/security/rating/", 50 | "Description": "SUSE Security Ratings" 51 | }, 52 | { 53 | "URL": "https://bugzilla.suse.com/1198976", 54 | "Description": "SUSE Bug 1198976" 55 | }, 56 | { 57 | "URL": "https://www.suse.com/security/cve/CVE-2022-29869/", 58 | "Description": "SUSE CVE CVE-2022-29869 page" 59 | } 60 | ], 61 | "Vulnerabilities": [ 62 | { 63 | "CVE": "CVE-2022-29869", 64 | "Description": "cifs-utils through 6.14, with verbose logging, can cause an information leak when a file contains = (equal sign) characters but is not a valid credentials file.", 65 | "Threats": [ 66 | { 67 | "Type": "Impact", 68 | "Severity": "moderate" 69 | } 70 | ], 71 | "References": [ 72 | { 73 | "URL": "https://www.suse.com/security/cve/CVE-2022-29869.html", 74 | "Description": "CVE-2022-29869" 75 | }, 76 | { 77 | "URL": "https://bugzilla.suse.com/1198976", 78 | "Description": "SUSE Bug 1198976" 79 | } 80 | ], 81 | "ProductStatuses": [ 82 | { 83 | "Type": "Fixed", 84 | "ProductID": [ 85 | "openSUSE Leap Micro 5.2:cifs-utils-6.9-150100.5.18.1" 86 | ] 87 | } 88 | ], 89 | "CVSSScoreSets": {} 90 | } 91 | ] 92 | } -------------------------------------------------------------------------------- /test/data/osv_mixed_data.json: -------------------------------------------------------------------------------- 1 | {"affected":[{"database_specific":{"cvss":{"score":7.3,"vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"},"cwes":[{"cweId":"CWE-843","description":"The program allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.","name":"Access of Resource Using Incompatible Type ('Type Confusion')"},{"cweId":"CWE-1321","description":"The software receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.","name":"Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')"}],"ghsa":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"},"package":{"ecosystem":"npm","name":"set-value"},"ranges":[{"events":[{"introduced":"0"},{"fixed":"2.0.1"},{"introduced":"3.0.0"},{"fixed":"4.0.1"}],"id":0,"type":"SEMVER"}]},{"database_specific":{"cvss":{"score":7.3,"vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"},"cwes":[{"cweId":"CWE-843","description":"The program allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.","name":"Access of Resource Using Incompatible Type ('Type Confusion')"},{"cweId":"CWE-1321","description":"The software receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.","name":"Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')"}],"ghsa":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"},"package":{"ecosystem":"NuGet","name":"set-value-nuget"},"ranges":[{"events":[{"introduced":"0"},{"fixed":"2.0.0"}],"id":0,"type":"ECOSYSTEM"}]}],"aliases":["CVE-2021-23440"],"details":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","id":"GHSA-4jqc-8m5r-9rpr","invalid":false,"isFixed":true,"modified":"2021-11-12T22:48:18Z","published":"2021-09-13T20:09:36Z","references":[{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2021-23440"},{"type":"WEB","url":"https://github.com/jonschlinkert/set-value/pull/33"},{"type":"WEB","url":"https://github.com/jonschlinkert/set-value/commit/7cf8073bb06bf0c15e08475f9f952823b4576452"},{"type":"WEB","url":"https://snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-1584212"},{"type":"WEB","url":"https://snyk.io/vuln/SNYK-JS-SETVALUE-1540541"},{"type":"WEB","url":"https://www.huntr.dev/bounties/2eae1159-01de-4f82-a177-7478a408c4a2/"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}],"source":"https://storage.googleapis.com/ghsa-osv/GHSA-4jqc-8m5r-9rpr.json","source_link":"https://storage.googleapis.com/ghsa-osv/GHSA-4jqc-8m5r-9rpr.json","summary":"Prototype Pollution in set-value"} 2 | -------------------------------------------------------------------------------- /test/data/RLSA-2022-7730.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "RLSA-2022:7730", 3 | "title": "Moderate: libldb security, bug fix, and enhancement update", 4 | "issued": { 5 | "date": "2022-11-13 07:54:11" 6 | }, 7 | "updated": { 8 | "date": "2022-11-08 00:00:00" 9 | }, 10 | "severity": "SEVERITY_MODERATE", 11 | "description": "The libldb packages provide an extensible library that implements an LDAP-like API to access remote LDAP servers, or use local TDB databases.\nThe following packages have been upgraded to a later upstream version: libldb (2.5.2). (BZ#2077484)\nFor more details about the security issue(s), including the impact, a CVSS score, acknowledgments, and other related information, refer to the CVE page(s) listed in the References section.\nAdditional Changes:\nFor detailed information on changes in this release, see the Rocky Linux 8.7 Release Notes linked from the References section.", 12 | "packages": [ 13 | { 14 | "name": "ldb-tools", 15 | "epoch": "0", 16 | "version": "2.5.2", 17 | "release": "2.el8", 18 | "arch": "x86_64", 19 | "src": "libldb-2.5.2-2.el8.src.rpm", 20 | "filename": "ldb-tools-2.5.2-2.el8.x86_64.rpm" 21 | }, 22 | { 23 | "name": "libldb", 24 | "epoch": "0", 25 | "version": "2.5.2", 26 | "release": "2.el8", 27 | "arch": "i686", 28 | "src": "libldb-2.5.2-2.el8.src.rpm", 29 | "filename": "libldb-2.5.2-2.el8.i686.rpm" 30 | }, 31 | { 32 | "name": "libldb", 33 | "epoch": "0", 34 | "version": "2.5.2", 35 | "release": "2.el8", 36 | "arch": "x86_64", 37 | "src": "libldb-2.5.2-2.el8.src.rpm", 38 | "filename": "libldb-2.5.2-2.el8.x86_64.rpm" 39 | }, 40 | { 41 | "name": "libldb-devel", 42 | "epoch": "0", 43 | "version": "2.5.2", 44 | "release": "2.el8", 45 | "arch": "i686", 46 | "src": "libldb-2.5.2-2.el8.src.rpm", 47 | "filename": "libldb-devel-2.5.2-2.el8.i686.rpm" 48 | }, 49 | { 50 | "name": "libldb-devel", 51 | "epoch": "0", 52 | "version": "2.5.2", 53 | "release": "2.el8", 54 | "arch": "x86_64", 55 | "src": "libldb-2.5.2-2.el8.src.rpm", 56 | "filename": "libldb-devel-2.5.2-2.el8.x86_64.rpm" 57 | }, 58 | { 59 | "name": "python3-ldb", 60 | "epoch": "0", 61 | "version": "2.5.2", 62 | "release": "2.el8", 63 | "arch": "i686", 64 | "src": "libldb-2.5.2-2.el8.src.rpm", 65 | "filename": "python3-ldb-2.5.2-2.el8.i686.rpm" 66 | }, 67 | { 68 | "name": "python3-ldb", 69 | "epoch": "0", 70 | "version": "2.5.2", 71 | "release": "2.el8", 72 | "arch": "x86_64", 73 | "src": "libldb-2.5.2-2.el8.src.rpm", 74 | "filename": "python3-ldb-2.5.2-2.el8.x86_64.rpm" 75 | } 76 | ], 77 | "references": [ 78 | { 79 | "href": "https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2022-32746.json", 80 | "id": "CVE-2022-32746", 81 | "title": "Update information for CVE-2022-32746 is retrieved from Red Hat", 82 | "type": "cve" 83 | } 84 | ], 85 | "cveids": [ 86 | "CVE-2022-32746" 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /test/data/CVE-2024-3801.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "CVE-2024-3801", 3 | "sourceIdentifier": "cvd@cert.pl", 4 | "published": "2024-06-28T13:15:03.157", 5 | "lastModified": "2024-07-03T14:36:52.797", 6 | "vulnStatus": "Analyzed", 7 | "descriptions": [ 8 | { 9 | "lang": "en", 10 | "value": "Sites managed in S@M CMS (Concept Intermedia) might be vulnerable to Reflected XSS via including scripts in one of GET header parameters. \nOnly a part of observed services is vulnerable, but since vendor has not investigated the root problem, it is hard to determine when the issue appears." 11 | }, 12 | { 13 | "lang": "es", 14 | "value": "Los sitios administrados en S@M CMS (Concept Intermedia) pueden ser vulnerables a XSS Reflejado al incluir scripts en uno de los parámetros del encabezado GET. Sólo una parte de los servicios observados es vulnerable, pero como el proveedor no ha investigado la raíz del problema, es difícil determinar cuándo aparece el problema." 15 | } 16 | ], 17 | "metrics": { 18 | "cvssMetricV31": [ 19 | { 20 | "source": "nvd@nist.gov", 21 | "type": "Primary", 22 | "cvssData": { 23 | "version": "3.1", 24 | "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", 25 | "attackVector": "NETWORK", 26 | "attackComplexity": "LOW", 27 | "privilegesRequired": "NONE", 28 | "userInteraction": "REQUIRED", 29 | "scope": "CHANGED", 30 | "confidentialityImpact": "LOW", 31 | "integrityImpact": "LOW", 32 | "availabilityImpact": "NONE", 33 | "baseScore": 6.1, 34 | "baseSeverity": "MEDIUM" 35 | }, 36 | "exploitabilityScore": 2.8, 37 | "impactScore": 2.7 38 | } 39 | ] 40 | }, 41 | "weaknesses": [ 42 | { 43 | "source": "nvd@nist.gov", 44 | "type": "Primary", 45 | "description": [ 46 | { 47 | "lang": "en", 48 | "value": "CWE-79" 49 | } 50 | ] 51 | }, 52 | { 53 | "source": "cvd@cert.pl", 54 | "type": "Secondary", 55 | "description": [ 56 | { 57 | "lang": "en", 58 | "value": "CWE-79" 59 | } 60 | ] 61 | } 62 | ], 63 | "configurations": [ 64 | { 65 | "nodes": [ 66 | { 67 | "operator": "OR", 68 | "negate": false, 69 | "cpeMatch": [ 70 | { 71 | "vulnerable": true, 72 | "criteria": "cpe:2.3:a:conceptintermedia:s\\@m_cms:*:*:*:*:*:*:*:*", 73 | "matchCriteriaId": "00A1AF5A-47FF-4080-A506-DB634A54CD6C", 74 | "versionEndIncluding": "3.3" 75 | } 76 | ] 77 | } 78 | ] 79 | } 80 | ], 81 | "references": [ 82 | { 83 | "url": "https://cert.pl/en/posts/2024/06/CVE-2024-3800", 84 | "source": "cvd@cert.pl", 85 | "tags": [ 86 | "Third Party Advisory" 87 | ] 88 | }, 89 | { 90 | "url": "https://cert.pl/posts/2024/06/CVE-2024-3800", 91 | "source": "cvd@cert.pl", 92 | "tags": [ 93 | "Third Party Advisory" 94 | ] 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /test/data/osv_swift_data2.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.4.0", 3 | "id": "GHSA-r6r4-5pr8-gjcp", 4 | "modified": "2024-01-03T21:44:35Z", 5 | "published": "2024-01-03T21:44:35Z", 6 | "aliases": [ 7 | "CVE-2024-21631" 8 | ], 9 | "summary": "Vapor contains an integer overflow in URI leading to potential host spoofing", 10 | "details": "Vapor's `vapor_urlparser_parse` function uses `uint16_t` indexes when parsing a URI's components, which may cause integer overflows when parsing untrusted inputs.\n\nThis vulnerability does not affect Vapor directly but could impact applications relying on the URI type for validating user input. \n\nThe URI type is used in several places in Vapor. A developer may decide to use URI to represent a URL in their application (especially if that URL is then passed to the HTTP Client) and rely on its public properties and methods. However, URI may fail to properly parse a valid (albeit abnormally long) URL, due to string ranges being converted to 16-bit integers. An attacker may use this behaviour to trick the application into accepting a URL to an untrusted destination.\n\nBy padding the port number with zeros, an attacker can cause an integer overflow to occur when the URL authority is parsed and, as a result, spoof the host.\n\n### Impact\nUsers attempting to treat untrusted input as a URI are vulnerable to a host spoofing attack due to an integer overflow.\n\n### Workarounds\nValidate user input before parsing as a URI or, if possible, use Foundation's `URL` and `URLComponents` utilities.", 11 | "severity": [ 12 | { 13 | "type": "CVSS_V3", 14 | "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N" 15 | } 16 | ], 17 | "affected": [ 18 | { 19 | "package": { 20 | "ecosystem": "SwiftURL", 21 | "name": "https://github.com/vapor/vapor" 22 | }, 23 | "ranges": [ 24 | { 25 | "type": "ECOSYSTEM", 26 | "events": [ 27 | { 28 | "introduced": "0" 29 | }, 30 | { 31 | "fixed": "4.90.0" 32 | } 33 | ] 34 | } 35 | ], 36 | "database_specific": { 37 | "last_known_affected_version_range": "<= 4.89.3" 38 | } 39 | } 40 | ], 41 | "references": [ 42 | { 43 | "type": "WEB", 44 | "url": "https://github.com/vapor/vapor/security/advisories/GHSA-r6r4-5pr8-gjcp" 45 | }, 46 | { 47 | "type": "ADVISORY", 48 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-21631" 49 | }, 50 | { 51 | "type": "WEB", 52 | "url": "https://github.com/vapor/vapor/commit/6db3d917b5ce5024a84eb265ef65691383305d70" 53 | }, 54 | { 55 | "type": "PACKAGE", 56 | "url": "https://github.com/vapor/vapor" 57 | } 58 | ], 59 | "database_specific": { 60 | "cwe_ids": [ 61 | "CWE-1104", 62 | "CWE-190" 63 | ], 64 | "severity": "MODERATE", 65 | "github_reviewed": true, 66 | "github_reviewed_at": "2024-01-03T21:44:35Z", 67 | "nvd_published_at": "2024-01-03T17:15:12Z" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /data/tags/reference-tags.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://cve.mitre.org/cve/v5_00/tags/reference/", 4 | "type": "string", 5 | "description": "broken-link: The reference link is returning a 404 error, or the site is no longer online.\n\ncustomer-entitlement: Similar to Privileges Required, but specific to references that require non-public/paid access for customers of the particular vendor.\n\nexploit: Reference contains an in-depth/detailed description of steps to exploit a vulnerability OR the reference contains any legitimate Proof of Concept (PoC) code or exploit kit.\n\ngovernment-resource: All reference links that are from a government agency or organization should be given the Government Resource tag.\n\nissue-tracking: The reference is a post from a bug tracking tool such as MantisBT, Bugzilla, JIRA, Github Issues, etc...\n\nmailing-list: The reference is from a mailing list -- often specific to a product or vendor.\n\nmitigation: The reference contains information on steps to mitigate against the vulnerability in the event a patch can't be applied or is unavailable or for EOL product situations.\n\nnot-applicable: The reference link is not applicable to the vulnerability and was likely associated by MITRE accidentally (should be used sparingly).\n\npatch: The reference contains an update to the software that fixes the vulnerability.\n\npermissions-required: The reference link provided is blocked by a logon page. If credentials are required to see any information this tag must be applied.\n\nmedia-coverage: The reference is from a media outlet such as a newspaper, magazine, social media, or weblog. This tag is not intended to apply to any individual's personal social media account. It is strictly intended for public media entities.\n\nproduct: A reference appropriate for describing a product for the purpose of CPE or SWID.\n\nrelated: A reference that is for a related (but not the same) vulnerability.\n\nrelease-notes: The reference is in the format of a vendor or open source project's release notes or change log.\n\nsignature: The reference contains a method to detect or prevent the presence or exploitation of the vulnerability.\n\ntechnical-description: The reference contains in-depth technical information about a vulnerability and its exploitation process, typically in the form of a presentation or whitepaper.\n\nthird-party-advisory: Advisory is from an organization that is not the vulnerable product's vendor/publisher/maintainer.\n\nvendor-advisory: Advisory is from the vendor/publisher/maintainer of the product or the parent organization.\n\nvdb-entry: VDBs are loosely defined as sites that provide information about this vulnerability, such as advisories, with identifiers. Included VDBs are free to access, substantially public, and have broad scope and coverage (not limited to a single vendor or research organization). See: https://www.first.org/global/sigs/vrdx/vdb-catalog", 6 | "enum": [ 7 | "broken-link", 8 | "customer-entitlement", 9 | "exploit", 10 | "government-resource", 11 | "issue-tracking", 12 | "mailing-list", 13 | "mitigation", 14 | "not-applicable", 15 | "patch", 16 | "permissions-required", 17 | "media-coverage", 18 | "product", 19 | "related", 20 | "release-notes", 21 | "signature", 22 | "technical-description", 23 | "third-party-advisory", 24 | "vendor-advisory", 25 | "vdb-entry" 26 | ] 27 | } -------------------------------------------------------------------------------- /test/data/osv_mvn_data.json: -------------------------------------------------------------------------------- 1 | {"affected":[{"database_specific":{"cvss":{"score":7.0,"vectorString":"CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H"},"cwes":[{"cweId":"CWE-470","description":"The application uses external input with reflection to select which classes or code to use, but it does not sufficiently prevent the input from selecting improper classes or code.","name":"Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')"}],"ghsa":"https://github.com/advisories/GHSA-xxgp-pcfc-3vgc"},"package":{"ecosystem":"Maven","name":"org.hibernate:hibernate-validator"},"ranges":[{"events":[{"introduced":"5.4.0"},{"fixed":"5.4.2"},{"introduced":"5.3.0"},{"fixed":"5.3.6"},{"introduced":"5.2.0"},{"fixed":"5.2.5"}],"id":0,"type":"ECOSYSTEM"}],"versions":["5.2.0.Final","5.2.1.Final","5.2.2.Final","5.2.3.Final","5.2.4.Final","5.3.0.Final","5.3.1.Final","5.3.2.Final","5.3.3.Final","5.3.4.Final","5.3.5.Final","5.4.0.Final","5.4.1.Final"]}],"aliases":["CVE-2019-7536"],"details":"In Hibernate Validator 5.2.x before 5.2.5 final, 5.3.x, and 5.4.x, it was found that when the security manager's reflective permissions, which allows it to access the private members of the class, are granted to Hibernate Validator, a potential privilege escalation can occur. By allowing the calling code to access those private members without the permission an attacker may be able to validate an invalid instance and access the private member value via ConstraintViolation#getInvalidValue().","id":"GHSA-xxgp-pcfc-3vgc","invalid":false,"isFixed":true,"modified":"2021-12-13T23:44:21.151108Z","published":"2020-06-15T19:57:48Z","references":[{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2017-7536"},{"type":"WEB","url":"https://bugzilla.redhat.com/show_bug.cgi?id=1465573"},{"type":"WEB","url":"https://lists.apache.org/thread.html/9317fd092b257a0815434b116a8af8daea6e920b6673f4fd5583d5fe@%3Ccommits.druid.apache.org%3E"},{"type":"WEB","url":"http://www.securityfocus.com/bid/101048"},{"type":"WEB","url":"http://www.securitytracker.com/id/1039744"},{"type":"WEB","url":"https://github.com/hibernate/hibernate-validator/commit/0778a5c98b817771a645c6f4ba0b28dd8b5437b"},{"type":"WEB","url":"https://github.com/hibernate/hibernate-validator/commit/0886e89900d343ea20fde5137c9a3086e6da9ac"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:2808"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:2809"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:2810"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:2811"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:3141"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:3454"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:3455"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:3456"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2017:3458"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:2740"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:2741"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:2742"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:2743"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:2927"},{"type":"WEB","url":"https://access.redhat.com/errata/RHSA-2018:3817"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-xxgp-pcfc-3vgc"}],"source":"https://storage.googleapis.com/ghsa-osv/GHSA-xxgp-pcfc-3vgc.json","source_link":"https://storage.googleapis.com/ghsa-osv/GHSA-xxgp-pcfc-3vgc.json","summary":"Privilege Escalation in Hibernate Validator"} 2 | -------------------------------------------------------------------------------- /.github/workflows/pythonpublish.yml: -------------------------------------------------------------------------------- 1 | name: Upload vdb Python Package 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - '**/README.md' 7 | branches: 8 | - master 9 | - release/* 10 | tags: 11 | - 'v*' 12 | workflow_dispatch: 13 | 14 | jobs: 15 | vdb-pypi: 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: write 19 | packages: write 20 | id-token: write 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Set up Python 24 | uses: actions/setup-python@v5 25 | with: 26 | python-version: '3.12' 27 | - name: Install uv 28 | uses: astral-sh/setup-uv@v5 29 | - name: Use Node.js 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: '25.x' 33 | - name: Set up JDK 34 | uses: actions/setup-java@v4 35 | with: 36 | distribution: 'temurin' 37 | java-version: '25' 38 | - name: Install dependencies 39 | run: | 40 | uv sync --all-extras --dev 41 | - name: Build 42 | run: | 43 | uv build 44 | - name: Publish package distributions to PyPI 45 | if: startsWith(github.ref, 'refs/tags/') 46 | run: | 47 | uv publish 48 | - name: Generate SBOM with cdxgen 49 | run: | 50 | npm install -g @cyclonedx/cdxgen 51 | cdxgen -t python -o bom.json . --deep 52 | env: 53 | FETCH_LICENSE: true 54 | - name: Create Release 55 | id: create_release 56 | if: startsWith(github.ref, 'refs/tags/') 57 | uses: softprops/action-gh-release@v2 58 | with: 59 | files: | 60 | bom.json 61 | env: 62 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | mcp-container: 65 | runs-on: ubuntu-latest 66 | needs: vdb-pypi 67 | permissions: 68 | contents: write 69 | packages: write 70 | id-token: write 71 | steps: 72 | - uses: actions/checkout@v4 73 | - name: Set up Python 74 | uses: actions/setup-python@v5 75 | with: 76 | python-version: '3.12' 77 | - name: Install uv 78 | uses: astral-sh/setup-uv@v5 79 | - name: Install dependencies 80 | run: | 81 | cd packages/mcp-server-vdb 82 | uv sync --all-extras --dev 83 | uv run pytest 84 | rm -rf .venv .coverage 85 | - name: Set up QEMU 86 | uses: docker/setup-qemu-action@v3 87 | - name: Set up Docker Buildx 88 | uses: docker/setup-buildx-action@v3 89 | - name: Log in to the Container registry 90 | uses: docker/login-action@v3 91 | with: 92 | registry: ghcr.io 93 | username: ${{ github.actor }} 94 | password: ${{ secrets.GITHUB_TOKEN }} 95 | - name: Extract metadata (tags, labels) for Docker 96 | id: meta 97 | uses: docker/metadata-action@v5 98 | with: 99 | images: | 100 | ghcr.io/appthreat/mcp-server-vdb 101 | - name: Build and push Docker images 102 | uses: docker/build-push-action@v5 103 | with: 104 | context: packages/mcp-server-vdb 105 | platforms: linux/amd64,linux/arm64 106 | push: true 107 | tags: ${{ steps.meta.outputs.tags }} 108 | labels: ${{ steps.meta.outputs.labels }} 109 | cache-from: type=gha,scope=mcp-server-vdb 110 | cache-to: type=gha,mode=max,scope=mcp-server-vdb 111 | -------------------------------------------------------------------------------- /test/data/RUSTSEC-2024-0343.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "RUSTSEC-2024-0343", 3 | "summary": "Reduced entropy due to inadequate character set usage", 4 | "details": "## Description\n\nAffected versions of the nano-id crate incorrectly generated IDs using a reduced character set in the `nano_id::base62` and `nano_id::base58` functions. Specifically, the `base62` function used a character set of 32 symbols instead of the intended 62 symbols, and the `base58` function used a character set of 16 symbols instead of the intended 58 symbols. Additionally, the `nano_id::gen` macro is also affected when a custom character set that is not a power of 2 in size is specified.\n\nIt should be noted that `nano_id::base64` is not affected by this vulnerability.\n\n## Impact\n\nThis can result in a significant reduction in entropy, making the generated IDs predictable and vulnerable to brute-force attacks when the IDs are used in security-sensitive contexts such as session tokens or unique identifiers.\n\n## Patches\n\nThe flaws were corrected in commit [a9022772b2f1ce38929b5b81eccc670ac9d3ab23](https://github.com/viz-rs/nano-id/commit/a9022772b2f1ce38929b5b81eccc670ac9d3ab23) by updating the the `nano_id::gen` macro to use all specified characters correctly.\n\n## PoC\n\n```rust\nuse std::collections::BTreeSet;\n\nfn main() {\n test_base58();\n test_base62();\n}\n\nfn test_base58() {\n let mut produced_symbols = BTreeSet::new();\n\n for _ in 0..100_000 {\nid = \"RUSTSEC-2024-0343\"\n for c in id.chars() {\n produced_symbols.insert(c);\n }\n }\n\n println!(\n \"{} symbols generated from nano_id::base58\",\n produced_symbols.len()\n );\n}\n\nfn test_base62() {\n let mut produced_symbols = BTreeSet::new();\n\n for _ in 0..100_000 {\nid = \"RUSTSEC-2024-0343\"\n for c in id.chars() {\n produced_symbols.insert(c);\n }\n }\n\n println!(\n \"{} symbols generated from nano_id::base62\",\n produced_symbols.len()\n );\n}\n```", 5 | "modified": "2024-06-03T07:19:16Z", 6 | "published": "2024-06-03T12:00:00Z", 7 | "database_specific": { 8 | "license": "CC0-1.0" 9 | }, 10 | "references": [ 11 | { 12 | "type": "PACKAGE", 13 | "url": "https://crates.io/crates/nano-id" 14 | }, 15 | { 16 | "type": "ADVISORY", 17 | "url": "https://rustsec.org/advisories/RUSTSEC-2024-0343.html" 18 | } 19 | ], 20 | "affected": [ 21 | { 22 | "package": { 23 | "name": "nano-id", 24 | "ecosystem": "crates.io", 25 | "purl": "pkg:cargo/nano-id" 26 | }, 27 | "ranges": [ 28 | { 29 | "type": "SEMVER", 30 | "events": [ 31 | { 32 | "introduced": "0.0.0-0" 33 | }, 34 | { 35 | "fixed": "0.4.0" 36 | } 37 | ] 38 | } 39 | ], 40 | "ecosystem_specific": { 41 | "affected_functions": null, 42 | "affects": { 43 | "os": [], 44 | "functions": [ 45 | "nano_id::base58", 46 | "nano_id::base62", 47 | "nano_id::gen" 48 | ], 49 | "arch": [] 50 | } 51 | }, 52 | "database_specific": { 53 | "cvss": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L", 54 | "informational": null, 55 | "source": "https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2024-0343.json", 56 | "categories": [ 57 | "crypto-failure" 58 | ] 59 | } 60 | } 61 | ], 62 | "schema_version": "1.6.0", 63 | "severity": [ 64 | { 65 | "type": "CVSS_V3", 66 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L" 67 | } 68 | ] 69 | } -------------------------------------------------------------------------------- /test/data/osv-pypi-django.json: -------------------------------------------------------------------------------- 1 | {"id":"GHSA-2gwj-7jmv-h26r","summary":"SQL Injection in Django","details":"An issue was discovered in Django 2.2 before 2.2.28, 3.2 before 3.2.13, and 4.0 before 4.0.4. `QuerySet.annotate()`, `aggregate()`, and `extra()` methods are subject to SQL injection in column aliases via a crafted dictionary (with dictionary expansion) as the passed `**kwargs`.","aliases":["BIT-django-2022-28346","CVE-2022-28346","PYSEC-2022-190"],"modified":"2025-02-21T05:41:10.759178Z","published":"2022-04-13T00:00:33Z","database_specific":{"github_reviewed_at":"2022-04-22T20:33:03Z","github_reviewed":true,"severity":"CRITICAL","cwe_ids":["CWE-89"],"nvd_published_at":"2022-04-12T05:15:00Z"},"references":[{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2022-28346"},{"type":"WEB","url":"https://github.com/django/django/commit/2044dac5c6968441be6f534c4139bcf48c5c7e48"},{"type":"WEB","url":"https://github.com/django/django/commit/2c09e68ec911919360d5f8502cefc312f9e03c5d"},{"type":"WEB","url":"https://github.com/django/django/commit/800828887a0509ad1162d6d407e94d8de7eafc60"},{"type":"WEB","url":"https://github.com/django/django/commit/93cae5cb2f9a4ef1514cf1a41f714fef08005200"},{"type":"WEB","url":"https://docs.djangoproject.com/en/4.0/releases/security"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-2gwj-7jmv-h26r"},{"type":"PACKAGE","url":"https://github.com/django/django"},{"type":"WEB","url":"https://github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2022-190.yaml"},{"type":"WEB","url":"https://groups.google.com/forum/#!forum/django-announce"},{"type":"WEB","url":"https://lists.debian.org/debian-lts-announce/2022/04/msg00013.html"},{"type":"WEB","url":"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HWY6DQWRVBALV73BPUVBXC3QIYUM24IK"},{"type":"WEB","url":"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LTZVAKU5ALQWOKFTPISE257VCVIYGFQI"},{"type":"WEB","url":"https://security.netapp.com/advisory/ntap-20220609-0002"},{"type":"WEB","url":"https://www.debian.org/security/2022/dsa-5254"},{"type":"WEB","url":"https://www.djangoproject.com/weblog/2022/apr/11/security-releases"},{"type":"WEB","url":"http://www.openwall.com/lists/oss-security/2022/04/11/1"}],"affected":[{"package":{"name":"django","ecosystem":"PyPI","purl":"pkg:pypi/django"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.2"},{"fixed":"2.2.28"}]}],"versions":["2.2","2.2.1","2.2.10","2.2.11","2.2.12","2.2.13","2.2.14","2.2.15","2.2.16","2.2.17","2.2.18","2.2.19","2.2.2","2.2.20","2.2.21","2.2.22","2.2.23","2.2.24","2.2.25","2.2.26","2.2.27","2.2.3","2.2.4","2.2.5","2.2.6","2.2.7","2.2.8","2.2.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/04/GHSA-2gwj-7jmv-h26r/GHSA-2gwj-7jmv-h26r.json"}},{"package":{"name":"django","ecosystem":"PyPI","purl":"pkg:pypi/django"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.2"},{"fixed":"3.2.13"}]}],"versions":["3.2","3.2.1","3.2.10","3.2.11","3.2.12","3.2.2","3.2.3","3.2.4","3.2.5","3.2.6","3.2.7","3.2.8","3.2.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/04/GHSA-2gwj-7jmv-h26r/GHSA-2gwj-7jmv-h26r.json"}},{"package":{"name":"django","ecosystem":"PyPI","purl":"pkg:pypi/django"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0"},{"fixed":"4.0.4"}]}],"versions":["4.0","4.0.1","4.0.2","4.0.3"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/04/GHSA-2gwj-7jmv-h26r/GHSA-2gwj-7jmv-h26r.json"}}],"schema_version":"1.6.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"}]} -------------------------------------------------------------------------------- /test/test_npm.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | import pytest 5 | 6 | from vdb.lib.npm import NpmSource 7 | 8 | 9 | @pytest.fixture 10 | def test_app_info(): 11 | return {"name": "appthreat-vulnerability-db-test", "version": "1.0.0"} 12 | 13 | 14 | @pytest.fixture 15 | def test_pkg_list(): 16 | return ["handlebars|4.1.0", "growl|1.10.0"] 17 | 18 | 19 | @pytest.fixture 20 | def test_cve_json(): 21 | test_cve_data = os.path.join( 22 | os.path.dirname(os.path.realpath(__file__)), "data", "npm_data.json" 23 | ) 24 | with open(test_cve_data, "r") as fp: 25 | return json.loads(fp.read()) 26 | 27 | 28 | def test_bulk_search(test_app_info, test_pkg_list): 29 | data = NpmSource().bulk_search(test_app_info, test_pkg_list) 30 | assert len(data) >= 7 31 | assert data[0].id.startswith("NPM-") 32 | 33 | 34 | def test_version_ranges(): 35 | source = NpmSource() 36 | version_list = source.get_version_ranges("<1.10.2") 37 | assert version_list == [ 38 | { 39 | "version_start_including": "", 40 | "version_end_including": "", 41 | "version_start_excluding": "", 42 | "version_end_excluding": "1.10.2", 43 | } 44 | ] 45 | version_list = source.get_version_ranges("<=4.0.13 || >=4.1.0 <4.1.2") 46 | assert version_list == [ 47 | { 48 | "version_start_including": "", 49 | "version_end_including": "4.0.13", 50 | "version_start_excluding": "", 51 | "version_end_excluding": "", 52 | }, 53 | { 54 | "version_start_including": "4.1.0", 55 | "version_end_including": "", 56 | "version_start_excluding": "", 57 | "version_end_excluding": "4.1.2", 58 | }, 59 | ] 60 | version_list = source.get_version_ranges(">=4.3.0") 61 | assert version_list == [ 62 | { 63 | "version_start_including": "4.3.0", 64 | "version_end_including": "", 65 | "version_start_excluding": "", 66 | "version_end_excluding": "", 67 | } 68 | ] 69 | version_list = source.get_version_ranges("1.1.0") 70 | assert version_list == [ 71 | { 72 | "version_start_including": "1.1.0", 73 | "version_end_including": "", 74 | "version_start_excluding": "", 75 | "version_end_excluding": "", 76 | } 77 | ] 78 | version_list = source.get_version_ranges(">= 0.6.1") 79 | assert version_list == [ 80 | { 81 | "version_start_including": "0.6.1", 82 | "version_end_including": "", 83 | "version_start_excluding": "", 84 | "version_end_excluding": "", 85 | } 86 | ] 87 | version_list = source.get_version_ranges(">= 1.4.1 < 2.0.0 || >= 2.0.3") 88 | assert version_list == [ 89 | { 90 | "version_start_including": "1.4.1", 91 | "version_end_including": "", 92 | "version_start_excluding": "", 93 | "version_end_excluding": "2.0.0", 94 | }, 95 | { 96 | "version_start_including": "2.0.3", 97 | "version_end_including": "", 98 | "version_start_excluding": "", 99 | "version_end_excluding": "", 100 | }, 101 | ] 102 | 103 | 104 | def test_convert(test_cve_json): 105 | data = NpmSource().convert(test_cve_json) 106 | assert len(data) == 8 107 | assert data[0][0].id == "CVE-2019-16042" 108 | 109 | 110 | @pytest.mark.skip(reason="Npm source is no longer available") 111 | def test_download_recent(): 112 | data = NpmSource().download_recent() 113 | assert len(data) >= 100 114 | 115 | 116 | @pytest.mark.skip(reason="This downloads and tests with live data") 117 | def test_download_all(): 118 | data = NpmSource().download_all() 119 | assert len(data) >= 100 120 | -------------------------------------------------------------------------------- /packages/mcp-server-vdb/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This folder contains the source code for running VDB as a Model Context Protocol (MCP) server. Below you can find the configuration for running the VDB MCP server with Claude Desktop. Please feel free to share the configuration for other [clients](https://modelcontextprotocol.io/clients) via pull requests. 4 | 5 | ## Pre-requisites 6 | 7 | - Python >= 3.10 installed 8 | - docker or Rancher Desktop (or) 9 | - uv [installed](https://docs.astral.sh/uv/getting-started/installation/) 10 | 11 | ## docker-based execution (Recommended) 12 | 13 | Use our container image `ghcr.io/appthreat/mcp-server-vdb:master`. 14 | 15 | ### Claude Desktop configuration 16 | 17 | Edit the file using VS code or any editor of your choice. `~/Library/Application Support/Claude/claude_desktop_config.json`. On Windows, the config file is `$env:AppData\Claude\claude_desktop_config.json`. Use the below configuration: 18 | 19 | ```json 20 | { 21 | "mcpServers": { 22 | "vdb": { 23 | "command": "docker", 24 | "args": [ 25 | "run", 26 | "-i", 27 | "--rm", 28 | "-e", 29 | "VDB_HOME=/db", 30 | "-v", 31 | "$HOME/vdb:/db:rw", 32 | "ghcr.io/appthreat/mcp-server-vdb:master" 33 | ] 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | `nerdctl` example. 40 | 41 | ```json 42 | { 43 | "mcpServers": { 44 | "vdb": { 45 | "command": "nerdctl", 46 | "args": [ 47 | "run", "-i", "--rm", "-e", "VDB_HOME=/db", "-v", "$HOME/vdb:/db:rw", "ghcr.io/appthreat/mcp-server-vdb:master" 48 | ] 49 | } 50 | } 51 | } 52 | ``` 53 | 54 | Restart the Claude Desktop application. 55 | 56 | If you get `ENOENT` error, specify the full path to docker. On a mac, `/Applications/Docker.app/Contents/Resources/bin/docker`. 57 | 58 | ## Local uv-based execution (Developers only) 59 | 60 | ```shell 61 | git clone https://github.com/AppThreat/vulnerability-db.git 62 | cd vulnerability-db 63 | python -m pip install . 64 | 65 | export VDB_HOME=$HOME/vdb 66 | mkdir -p $VDB_HOME 67 | vdb --download-image 68 | uv --directory contrib/mcp-server-vdb run mcp-server-vdb 69 | ``` 70 | 71 | ### Claude Desktop configuration 72 | 73 | Edit the file using VS code or any editor of your choice. `~/Library/Application Support/Claude/claude_desktop_config.json`. On Windows, the config file is `$env:AppData\Claude\claude_desktop_config.json`. 74 | 75 | Use the below configuration and adjust the following paths: 76 | 77 | - absolute path to the `mcp-server-vdb` inside the contrib directory. 78 | - `VDB_HOME` - Full path to the directory containing the vulnerability database. Must have run `vdb --download-image` 79 | 80 | ```json 81 | { 82 | "mcpServers": { 83 | "vdb": { 84 | "command": "uv", 85 | "args": [ 86 | "--directory", 87 | "/Volumes/Work/AppThreat/vulnerability-db/contrib/mcp-server-vdb", 88 | "run", 89 | "mcp-server-vdb" 90 | ], 91 | "env": { 92 | "VDB_HOME": "/Users/guest/vdb" 93 | } 94 | } 95 | } 96 | } 97 | ``` 98 | 99 | Restart the Claude Desktop application. 100 | 101 | ## Screenshots 102 | 103 | ### Claude context screen 104 | 105 | ![Claude context](./docs/claude-context.png) 106 | 107 | ### Claude permissions on first run 108 | 109 | ![Claude permissions](./docs/claude-permissions.png) 110 | 111 | ### Claude results 112 | 113 | ![Vulnerability description](./docs/vuln-description.png) 114 | 115 | ### Latest malware 116 | 117 | ![Latest Malware](./docs/latest-malware.png) 118 | 119 | ## Configuration for MCP Inspector 120 | 121 | - Transport Type: STDIO 122 | - Command: python 123 | - Arguments: vdb/server.py 124 | 125 | Click "Connect" 126 | 127 | ![MCP Inspector](./docs/vdb-mcp-inspector.png) 128 | 129 | ### Testing 130 | 131 | 1. Click "List Tools". Must see a list of tools such as `search_by_purl_like`, `search_by_any`, and so on. 132 | 2. Select `search_by_purl_like` and enter a purl string such as `pkg:swift/vapor/vapor@4.89.0`. 133 | -------------------------------------------------------------------------------- /.github/workflows/pythonapp.yml: -------------------------------------------------------------------------------- 1 | name: Python matrix CI 2 | 3 | on: 4 | pull_request: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, windows-latest, macos-15] 13 | python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] 14 | fail-fast: false 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Set up Python 18 | uses: actions/setup-python@v5 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Install uv 22 | uses: astral-sh/setup-uv@v5 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Display Python version 26 | run: python -c "import sys; print(sys.version)" 27 | - name: Use Node.js 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version: '25.x' 31 | - name: Set up JDK 32 | uses: actions/setup-java@v4 33 | with: 34 | distribution: 'temurin' 35 | java-version: '25' 36 | - name: Install dependencies 37 | run: | 38 | uv sync --all-extras --dev 39 | - name: Lint with flake8 40 | run: | 41 | uv run flake8 . --count --show-source --exit-zero --statistics 42 | - name: Test with pytest 43 | run: | 44 | uv run pytest --cov=vdb test 45 | env: 46 | PYTHONPATH: . 47 | TEST_VDB_HOME: vdb_data 48 | VDB_TEMP_DIR: ${{ runner.temp }}/vdb-temp 49 | - name: Generate SBOM with cdxgen 50 | run: | 51 | npm install -g @cyclonedx/cdxgen 52 | cdxgen -t python -o bom.json . -p --profile research 53 | if: ${{ matrix.python-version == '3.13' && matrix.os == 'ubuntu-latest' }} 54 | - name: CLI tests 55 | run: | 56 | uv sync --all-extras --dev 57 | uv run vdb --cache --only-osv 58 | uv run vdb --bom bom.json 59 | uv run vdb --search "pkg:maven/org.springframework/spring-core@6.0.13" 60 | uv run vdb --search "pkg:maven/org.hibernate.orm/hibernate-core@6.2.9.Final" 61 | uv run vdb --search "pkg:nuget/Microsoft.Data.SqlClient@5.0.1" 62 | uv run vdb --search "pkg:nuget/Microsoft.IdentityModel.JsonWebTokens@6.21.0" 63 | uv run vdb --search "pkg:nuget/System.Drawing.Common@5.0.0" 64 | uv run vdb --search "pkg:npm/eslint-config-prettier@9.1.0" 65 | uv run vdb --search "pkg:npm/eslint-config-prettier@9.1.1" 66 | uv run vdb --search "pkg:npm/eslint-config-prettier@10.1.7" 67 | uv run vdb --search "escape.tech:graphql-armor-max-depth:2.4.0" 68 | uv run vdb --search "pkg:npm/%40escape.tech/graphql-armor-max-depth@2.4.0" 69 | 70 | echo "Creating custom vulnerability file..." 71 | mkdir -p custom_vulns 72 | cat > custom_vulns/private.yaml < list[dict[str, str]]: 151 | """Tag the urls under references""" 152 | tags = [] 153 | for aref in ref_urls: 154 | theurl = aref.url if isinstance(aref, Reference) else aref 155 | for reference_tag, tag_patterns in REFERENCE_TAGS_MAP.items(): 156 | for keyword_str in tag_patterns: 157 | if keyword_str in theurl: 158 | tags.append({"url": theurl, "tag": reference_tag}) 159 | break 160 | return tags 161 | -------------------------------------------------------------------------------- /test/data/SUSE-SU-2022-4192-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "Title": "Security update for nginx", 3 | "Tracking": { 4 | "ID": "SUSE-SU-2022:4192-1", 5 | "Status": "Final", 6 | "Version": "1", 7 | "InitialReleaseDate": "2022-11-23T10:05:21Z", 8 | "CurrentReleaseDate": "2022-11-23T10:05:21Z", 9 | "RevisionHistory": [ 10 | { 11 | "Number": "1", 12 | "Date": "2022-11-23T10:05:21Z", 13 | "Description": "current" 14 | } 15 | ] 16 | }, 17 | "Notes": [ 18 | { 19 | "Text": "Security update for nginx", 20 | "Title": "Topic", 21 | "Type": "Summary" 22 | }, 23 | { 24 | "Text": "This update for nginx fixes the following issues:\n\n- CVE-2021-3618: Fixed the ALPACA attack limiting the number of errors after which the connection is closed (bsc#1187685).\n", 25 | "Title": "Details", 26 | "Type": "General" 27 | }, 28 | { 29 | "Text": "The CVRF data is provided by SUSE under the Creative Commons License 4.0 with Attribution (CC-BY-4.0).", 30 | "Title": "Terms of Use", 31 | "Type": "Legal Disclaimer" 32 | } 33 | ], 34 | "ProductTree": { 35 | "Relationships": [ 36 | { 37 | "ProductReference": "nginx-1.16.1-150000.3.18.1", 38 | "RelatesToProductReference": "SUSE Linux Enterprise High Performance Computing 15-ESPOS", 39 | "RelationType": "Default Component Of" 40 | }, 41 | { 42 | "ProductReference": "nginx-1.16.1-150000.3.18.1", 43 | "RelatesToProductReference": "SUSE Linux Enterprise High Performance Computing 15-LTSS", 44 | "RelationType": "Default Component Of" 45 | }, 46 | { 47 | "ProductReference": "nginx-1.16.1-150000.3.18.1", 48 | "RelatesToProductReference": "SUSE Linux Enterprise Server 15-LTSS", 49 | "RelationType": "Default Component Of" 50 | }, 51 | { 52 | "ProductReference": "nginx-1.16.1-150000.3.18.1", 53 | "RelatesToProductReference": "SUSE Linux Enterprise Server for SAP Applications 15", 54 | "RelationType": "Default Component Of" 55 | } 56 | ] 57 | }, 58 | "References": [ 59 | { 60 | "URL": "https://www.suse.com/support/update/announcement/2022/suse-su-20224192-1/", 61 | "Description": "Link for SUSE-SU-2022:4192-1" 62 | }, 63 | { 64 | "URL": "https://lists.suse.com/pipermail/sle-security-updates/2022-November/013089.html", 65 | "Description": "E-Mail link for SUSE-SU-2022:4192-1" 66 | }, 67 | { 68 | "URL": "https://www.suse.com/support/security/rating/", 69 | "Description": "SUSE Security Ratings" 70 | }, 71 | { 72 | "URL": "https://bugzilla.suse.com/1187685", 73 | "Description": "SUSE Bug 1187685" 74 | }, 75 | { 76 | "URL": "https://www.suse.com/security/cve/CVE-2021-3618/", 77 | "Description": "SUSE CVE CVE-2021-3618 page" 78 | } 79 | ], 80 | "Vulnerabilities": [ 81 | { 82 | "CVE": "CVE-2021-3618", 83 | "Description": "ALPACA is an application layer protocol content confusion attack, exploiting TLS servers implementing different protocols but using compatible certificates, such as multi-domain or wildcard certificates. A MiTM attacker having access to victim's traffic at the TCP/IP layer can redirect traffic from one subdomain to another, resulting in a valid TLS session. This breaks the authentication of TLS and cross-protocol attacks may be possible where the behavior of one protocol service may compromise the other at the application layer.", 84 | "Threats": [ 85 | { 86 | "Type": "Impact", 87 | "Severity": "important" 88 | } 89 | ], 90 | "References": [ 91 | { 92 | "URL": "https://www.suse.com/security/cve/CVE-2021-3618.html", 93 | "Description": "CVE-2021-3618" 94 | }, 95 | { 96 | "URL": "https://bugzilla.suse.com/1187678", 97 | "Description": "SUSE Bug 1187678" 98 | } 99 | ], 100 | "ProductStatuses": [ 101 | { 102 | "Type": "Fixed", 103 | "ProductID": [ 104 | "SUSE Linux Enterprise High Performance Computing 15-ESPOS:nginx-1.16.1-150000.3.18.1", 105 | "SUSE Linux Enterprise High Performance Computing 15-LTSS:nginx-1.16.1-150000.3.18.1", 106 | "SUSE Linux Enterprise Server 15-LTSS:nginx-1.16.1-150000.3.18.1", 107 | "SUSE Linux Enterprise Server for SAP Applications 15:nginx-1.16.1-150000.3.18.1" 108 | ] 109 | } 110 | ], 111 | "CVSSScoreSets": {} 112 | } 113 | ] 114 | } -------------------------------------------------------------------------------- /INTEGRATION.md: -------------------------------------------------------------------------------- 1 | # Integration guide 2 | 3 | This document provides useful information to help integrate VDB with your products and services. 4 | 5 | ## Pre-requisite 6 | 7 | When used as a Python library, the only dependency is Python >= 3.10. When using the sqlite database directly in your application, ensure the version of the SQLite3 [library](https://www.sqlite.org/download.html) is greater than 3.45.2. 8 | 9 | ## Database files 10 | 11 | The vulnerability database comprises two SQLite database files. 12 | 13 | - data.index.vdb6 - A smaller index database optimized for quick purl or cpe string searches and vers-based range comparisons. 14 | - data.vdb6 - Full CVE source database containing normalized data in CVE 5.2 specification formation and purl prefix. 15 | 16 | ### cve_index schema 17 | 18 | ```sql 19 | CREATE TABLE if not exists cve_index( 20 | cve_id TEXT NOT NULL, 21 | type TEXT NOT NULL, 22 | namespace TEXT, 23 | name TEXT NOT NULL, 24 | vers TEXT NOT NULL, 25 | purl_prefix TEXT NOT NULL 26 | ) 27 | ``` 28 | 29 | ### cve_data schema 30 | 31 | ```sql 32 | CREATE TABLE if not exists cve_data( 33 | cve_id TEXT NOT NULL, 34 | type TEXT NOT NULL, 35 | namespace TEXT, 36 | name TEXT NOT NULL, 37 | source_data BLOB NOT NULL, 38 | override_data BLOB, 39 | source_data_hash TEXT NOT NULL, 40 | vers TEXT NOT NULL, 41 | purl_prefix TEXT NOT NULL 42 | ) 43 | ``` 44 | 45 | ## Searching for CVEs 46 | 47 | Use the smaller index database for all search operations. 48 | 49 | ### Searching by purl 50 | 51 | Given a purl string (`purl_str`), perform the following steps to convert this into a suitable purl prefix (`purl_prefix`) string: 52 | 53 | In most cases, a purl prefix is a substring at index 0 after a split by "@". Eg: `purl_prefix = purl_str.split("@")[0]`. 54 | 55 | A more robust approach: 56 | 57 | - Parse and validate the string using a suitable [library](https://github.com/package-url/). Retain the parsed purl object (`purl_obj`) 58 | - Construct a purl prefix string with the following logic: 59 | - Set the value for `purl_prefix` to `"pkg:" + purl_obj["type"]` 60 | - If there is a namespace, append it to purl_prefix after the slash character. Eg: `purl_prefix = purl_prefix + "/" + purl_obj['namespace']` 61 | - Optional for Linux distros: If there is a qualifier string with the name `distro_name`, append it to the purl_prefix after the slash character. Eg: `purl_prefix = purl_prefix + "/" + purl_obj['qualifiers']['distro_name']` 62 | - Append the name after the slash character. Eg: `purl_prefix = purl_prefix + "/" + purl_obj['name']` 63 | 64 | Use the below SQL query to search by purl_prefix: 65 | 66 | ``` 67 | SELECT DISTINCT cve_id, type, namespace, name, vers, purl_prefix FROM cve_index where purl_prefix = ?; 68 | ``` 69 | 70 | ### Searching by cpe 71 | 72 | Parse the cpe string to extract the vendor, product, and version. The regex for python is shown below: 73 | 74 | ```python 75 | import re 76 | 77 | CPE_FULL_REGEX = re.compile( 78 | "cpe:?:[^:]+:(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+):(?P[^:]+)" 79 | ) 80 | ``` 81 | 82 | In the `cve_index` table, vendor maps to namespace and package maps to name. The SQL query is below: 83 | 84 | ```sql 85 | SELECT DISTINCT cve_id, type, namespace, name, vers, purl_prefix FROM cve_index where namespace = ? AND name = ?; 86 | ``` 87 | 88 | ### Comparing version ranges using vers 89 | 90 | Refer to the vers [documentation](https://github.com/package-url/purl-spec/blob/version-range-spec/VERSION-RANGE-SPEC.rst) for information regarding vers and a logic to parse and check if a version is within a range. To simplify the logic, a value from the vers column in `cve_index` would contain only a maximum of two constraints (one greater than and one lesser than). 91 | 92 | ## Combining data 93 | 94 | Search the `cve_index` table in the index database first to retrieve any matching cve_id and purl_prefix values. Use these two column values to retrieve the full CVE source information from the `cve_data` table. An example query is shown below: 95 | 96 | ```sql 97 | SELECT DISTINCT cve_id, type, namespace, name, source_data_hash, json(source_data), vers, purl_prefix FROM cve_data 98 | WHERE cve_id = ? AND vers = ? AND purl_prefix = ? 99 | GROUP BY purl_prefix 100 | ORDER BY cve_id DESC; 101 | ``` 102 | 103 | Use the `source_data_hash` values to filter out any duplicate results for the same CVE. Duplicate results are possible when multiple vers match the same CVE and purl prefixes. 104 | -------------------------------------------------------------------------------- /test/data/osv-pypi-ujson-bug.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "GHSA-wpqr-jcpx-745r", 3 | "summary": "Incorrect handling of invalid surrogate pair characters", 4 | "details": "### Impact\n_What kind of vulnerability is it? Who is impacted?_\n\nAnyone parsing JSON from an untrusted source is vulnerable.\n\nJSON strings that contain escaped surrogate characters not part of a proper surrogate pair were decoded incorrectly. Besides corrupting strings, this allowed for potential key confusion and value overwriting in dictionaries.\n\nExamples:\n\n```python\n# An unpaired high surrogate character is ignored.\n>>> ujson.loads(r'\"\\uD800\"')\n''\n>>> ujson.loads(r'\"\\uD800hello\"')\n'hello'\n\n# An unpaired low surrogate character is preserved.\n>>> ujson.loads(r'\"\\uDC00\"')\n'\\udc00'\n\n# A pair of surrogates with additional non surrogate characters pair up in spite of being invalid.\n>>> ujson.loads(r'\"\\uD800foo bar\\uDC00\"')\n'foo bar\ud800\udc00'\n```\n\n### Patches\n_Has the problem been patched? What versions should users upgrade to?_\n\nUsers should upgrade to UltraJSON 5.4.0.\n\nFrom version 5.4.0, UltraJSON decodes lone surrogates in the same way as the standard library's `json` module does, preserving them in the parsed output:\n\n```python3\n>>> ujson.loads(r'\"\\uD800\"')\n'\\ud800'\n>>> ujson.loads(r'\"\\uD800hello\"')\n'\\ud800hello'\n>>> ujson.loads(r'\"\\uDC00\"')\n'\\udc00'\n>>> ujson.loads(r'\"\\uD800foo bar\\uDC00\"')\n'\\ud800foo bar\\udc00'\n```\n\n### Workarounds\n_Is there a way for users to fix or remediate the vulnerability without upgrading?_\n\nShort of switching to an entirely different JSON library, there are no safe alternatives to upgrading.\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [UltraJSON](http://github.com/ultrajson/ultrajson/issues)\n", 5 | "aliases": [ 6 | "CVE-2022-31116" 7 | ], 8 | "modified": "2024-02-21T05:24:44.762164Z", 9 | "published": "2022-07-05T21:06:00Z", 10 | "database_specific": { 11 | "nvd_published_at": "2022-07-05T18:15:00Z", 12 | "cwe_ids": [ 13 | "CWE-670" 14 | ], 15 | "severity": "HIGH", 16 | "github_reviewed": true, 17 | "github_reviewed_at": "2022-07-05T21:06:00Z" 18 | }, 19 | "references": [ 20 | { 21 | "type": "WEB", 22 | "url": "https://github.com/ultrajson/ultrajson/security/advisories/GHSA-wpqr-jcpx-745r" 23 | }, 24 | { 25 | "type": "ADVISORY", 26 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-31116" 27 | }, 28 | { 29 | "type": "WEB", 30 | "url": "https://github.com/ultrajson/ultrajson/commit/67ec07183342589d602e0fcf7bb1ff3e19272687" 31 | }, 32 | { 33 | "type": "PACKAGE", 34 | "url": "https://github.com/ultrajson/ultrajson" 35 | }, 36 | { 37 | "type": "WEB", 38 | "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NAU5N4A7EUK2AMUCOLYDD5ARXAJYZBD2" 39 | }, 40 | { 41 | "type": "WEB", 42 | "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/OPPU5FZP3LCTXYORFH7NHUMYA5X66IA7" 43 | } 44 | ], 45 | "affected": [ 46 | { 47 | "package": { 48 | "name": "ujson", 49 | "ecosystem": "PyPI", 50 | "purl": "pkg:pypi/ujson" 51 | }, 52 | "ranges": [ 53 | { 54 | "type": "ECOSYSTEM", 55 | "events": [ 56 | { 57 | "introduced": "0" 58 | }, 59 | { 60 | "fixed": "5.4.0" 61 | } 62 | ] 63 | } 64 | ], 65 | "versions": [ 66 | "1.15", 67 | "1.18", 68 | "1.19", 69 | "1.21", 70 | "1.22", 71 | "1.23", 72 | "1.30", 73 | "1.33", 74 | "1.34", 75 | "1.35", 76 | "1.4", 77 | "1.6", 78 | "1.8", 79 | "1.9", 80 | "2.0.0", 81 | "2.0.1", 82 | "2.0.2", 83 | "2.0.3", 84 | "3.0.0", 85 | "3.1.0", 86 | "3.2.0", 87 | "4.0.0", 88 | "4.0.1", 89 | "4.0.2", 90 | "4.1.0", 91 | "4.2.0", 92 | "4.3.0", 93 | "5.0.0", 94 | "5.1.0", 95 | "5.2.0", 96 | "5.3.0" 97 | ], 98 | "database_specific": { 99 | "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/07/GHSA-wpqr-jcpx-745r/GHSA-wpqr-jcpx-745r.json" 100 | } 101 | } 102 | ], 103 | "schema_version": "1.6.0", 104 | "severity": [ 105 | { 106 | "type": "CVSS_V3", 107 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" 108 | } 109 | ] 110 | } -------------------------------------------------------------------------------- /test/data/osv-maven-cvss4.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.4.0", 3 | "id": "GHSA-gr3c-q7xf-47vh", 4 | "modified": "2024-11-08T18:49:15Z", 5 | "published": "2024-11-08T18:49:15Z", 6 | "aliases": [ 7 | "CVE-2024-52007" 8 | ], 9 | "summary": "XXE vulnerability in XSLT parsing in `org.hl7.fhir.core`", 10 | "details": "### Summary\nXSLT parsing performed by various components are vulnerable to XML external entity injections. A processed XML file with a malicious DTD tag ( ]> could produce XML containing data from the host system. This impacts use cases where org.hl7.fhir.core is being used to within a host where external clients can submit XML.\n\n### Details\nThis is related to https://github.com/hapifhir/org.hl7.fhir.core/security/advisories/GHSA-6cr6-ph3p-f5rf, in which its fix ( https://github.com/hapifhir/org.hl7.fhir.core/issues/1571, https://github.com/hapifhir/org.hl7.fhir.core/pull/1717) was incomplete. \n\n### References\nhttps://cwe.mitre.org/data/definitions/611.html\nhttps://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j", 11 | "severity": [ 12 | { 13 | "type": "CVSS_V3", 14 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N" 15 | }, 16 | { 17 | "type": "CVSS_V4", 18 | "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:N/SA:N" 19 | } 20 | ], 21 | "affected": [ 22 | { 23 | "package": { 24 | "ecosystem": "Maven", 25 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.dstu3" 26 | }, 27 | "ranges": [ 28 | { 29 | "type": "ECOSYSTEM", 30 | "events": [ 31 | { 32 | "introduced": "0" 33 | }, 34 | { 35 | "fixed": "6.4.0" 36 | } 37 | ] 38 | } 39 | ] 40 | }, 41 | { 42 | "package": { 43 | "ecosystem": "Maven", 44 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.r4" 45 | }, 46 | "ranges": [ 47 | { 48 | "type": "ECOSYSTEM", 49 | "events": [ 50 | { 51 | "introduced": "0" 52 | }, 53 | { 54 | "fixed": "6.4.0" 55 | } 56 | ] 57 | } 58 | ] 59 | }, 60 | { 61 | "package": { 62 | "ecosystem": "Maven", 63 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.r4b" 64 | }, 65 | "ranges": [ 66 | { 67 | "type": "ECOSYSTEM", 68 | "events": [ 69 | { 70 | "introduced": "0" 71 | }, 72 | { 73 | "fixed": "6.4.0" 74 | } 75 | ] 76 | } 77 | ] 78 | }, 79 | { 80 | "package": { 81 | "ecosystem": "Maven", 82 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.r5" 83 | }, 84 | "ranges": [ 85 | { 86 | "type": "ECOSYSTEM", 87 | "events": [ 88 | { 89 | "introduced": "0" 90 | }, 91 | { 92 | "fixed": "6.4.0" 93 | } 94 | ] 95 | } 96 | ] 97 | }, 98 | { 99 | "package": { 100 | "ecosystem": "Maven", 101 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.utilities" 102 | }, 103 | "ranges": [ 104 | { 105 | "type": "ECOSYSTEM", 106 | "events": [ 107 | { 108 | "introduced": "0" 109 | }, 110 | { 111 | "fixed": "6.4.0" 112 | } 113 | ] 114 | } 115 | ] 116 | }, 117 | { 118 | "package": { 119 | "ecosystem": "Maven", 120 | "name": "ca.uhn.hapi.fhir:org.hl7.fhir.dstu2016may" 121 | }, 122 | "ranges": [ 123 | { 124 | "type": "ECOSYSTEM", 125 | "events": [ 126 | { 127 | "introduced": "0" 128 | }, 129 | { 130 | "fixed": "6.4.0" 131 | } 132 | ] 133 | } 134 | ] 135 | } 136 | ], 137 | "references": [ 138 | { 139 | "type": "WEB", 140 | "url": "https://github.com/hapifhir/org.hl7.fhir.core/security/advisories/GHSA-gr3c-q7xf-47vh" 141 | }, 142 | { 143 | "type": "PACKAGE", 144 | "url": "https://github.com/hapifhir/org.hl7.fhir.core" 145 | } 146 | ], 147 | "database_specific": { 148 | "cwe_ids": [ 149 | "CWE-611" 150 | ], 151 | "severity": "HIGH", 152 | "github_reviewed": true, 153 | "github_reviewed_at": "2024-11-08T18:49:15Z", 154 | "nvd_published_at": null 155 | } 156 | } -------------------------------------------------------------------------------- /test/data/CVE-2021-27434.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "CVE-2021-27434", 3 | "sourceIdentifier": "ics-cert@hq.dhs.gov", 4 | "published": "2021-05-20T14:15:07.767", 5 | "lastModified": "2023-10-15T16:18:45.880", 6 | "vulnStatus": "Analyzed", 7 | "descriptions": [ 8 | { 9 | "lang": "en", 10 | "value": "Products with Unified Automation .NET based OPC UA Client/Server SDK Bundle: Versions V3.0.7 and prior (.NET 4.5, 4.0, and 3.5 Framework versions only) are vulnerable to an uncontrolled recursion, which may allow an attacker to trigger a stack overflow." 11 | }, 12 | { 13 | "lang": "es", 14 | "value": "Productos con el programa Unified Automation .NET based OPC UA Client/Server SDK Bundle: Versiones V3.0.7 y anteriores (solo versiones de .NET 4.5, 4.0 y 3.5 Framework) son vulnerables a una recursividad no controlada, que puede permitir a un atacante desencadenar un desbordamiento de pila" 15 | } 16 | ], 17 | "metrics": { 18 | "cvssMetricV31": [ 19 | { 20 | "source": "nvd@nist.gov", 21 | "type": "Primary", 22 | "cvssData": { 23 | "version": "3.1", 24 | "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", 25 | "attackVector": "NETWORK", 26 | "attackComplexity": "LOW", 27 | "privilegesRequired": "NONE", 28 | "userInteraction": "NONE", 29 | "scope": "UNCHANGED", 30 | "confidentialityImpact": "HIGH", 31 | "integrityImpact": "NONE", 32 | "availabilityImpact": "NONE", 33 | "baseScore": 7.5, 34 | "baseSeverity": "HIGH" 35 | }, 36 | "exploitabilityScore": 3.9, 37 | "impactScore": 3.6 38 | } 39 | ], 40 | "cvssMetricV2": [ 41 | { 42 | "source": "nvd@nist.gov", 43 | "type": "Primary", 44 | "cvssData": { 45 | "version": "2.0", 46 | "vectorString": "AV:N/AC:L/Au:N/C:P/I:N/A:N", 47 | "accessVector": "NETWORK", 48 | "accessComplexity": "LOW", 49 | "authentication": "NONE", 50 | "confidentialityImpact": "PARTIAL", 51 | "integrityImpact": "NONE", 52 | "availabilityImpact": "NONE", 53 | "baseScore": 5 54 | }, 55 | "baseSeverity": "MEDIUM", 56 | "exploitabilityScore": 10, 57 | "impactScore": 2.9, 58 | "acInsufInfo": false, 59 | "obtainAllPrivilege": false, 60 | "obtainUserPrivilege": false, 61 | "obtainOtherPrivilege": false, 62 | "userInteractionRequired": false 63 | } 64 | ] 65 | }, 66 | "weaknesses": [ 67 | { 68 | "source": "nvd@nist.gov", 69 | "type": "Primary", 70 | "description": [ 71 | { 72 | "lang": "en", 73 | "value": "CWE-674" 74 | } 75 | ] 76 | }, 77 | { 78 | "source": "ics-cert@hq.dhs.gov", 79 | "type": "Secondary", 80 | "description": [ 81 | { 82 | "lang": "en", 83 | "value": "CWE-200" 84 | } 85 | ] 86 | } 87 | ], 88 | "configurations": [ 89 | { 90 | "operator": "AND", 91 | "nodes": [ 92 | { 93 | "operator": "OR", 94 | "negate": false, 95 | "cpeMatch": [ 96 | { 97 | "vulnerable": true, 98 | "criteria": "cpe:2.3:a:unified-automation:.net_based_opc_ua_client\\/server_sdk:*:*:*:*:*:*:*:*", 99 | "matchCriteriaId": "72FFADD0-F648-492C-9A45-1456EEDAAD06", 100 | "versionEndIncluding": "3.0.7" 101 | } 102 | ] 103 | }, 104 | { 105 | "operator": "OR", 106 | "negate": false, 107 | "cpeMatch": [ 108 | { 109 | "vulnerable": false, 110 | "criteria": "cpe:2.3:a:microsoft:.net_framework:3.5:*:*:*:*:*:*:*", 111 | "matchCriteriaId": "E039CE1F-B988-4741-AE2E-5B36E2AF9688" 112 | }, 113 | { 114 | "vulnerable": false, 115 | "criteria": "cpe:2.3:a:microsoft:.net_framework:4.0:*:*:*:*:*:*:*", 116 | "matchCriteriaId": "792B417F-96A0-4E9D-9E79-5D7F982E2225" 117 | }, 118 | { 119 | "vulnerable": false, 120 | "criteria": "cpe:2.3:a:microsoft:.net_framework:4.5:*:*:*:*:*:*:*", 121 | "matchCriteriaId": "61FAD9EE-FA7F-4B39-8A9B-AFFAEC8BF214" 122 | } 123 | ] 124 | } 125 | ] 126 | } 127 | ], 128 | "references": [ 129 | { 130 | "url": "https://us-cert.cisa.gov/ics/advisories/icsa-21-133-04", 131 | "source": "ics-cert@hq.dhs.gov", 132 | "tags": [ 133 | "Third Party Advisory", 134 | "US Government Resource" 135 | ] 136 | } 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /test/data/CVE-2022-21824.json: -------------------------------------------------------------------------------- 1 | { 2 | "affected_release": [ 3 | { 4 | "product_name": "Red Hat Enterprise Linux 8", 5 | "release_date": "2022-06-21T00:00:00Z", 6 | "advisory": "RHEA-2022:5139", 7 | "package": "nodejs:12-8060020220523160029.ad008a3a", 8 | "cpe": "cpe:/a:redhat:enterprise_linux:8" 9 | }, 10 | { 11 | "product_name": "Red Hat Enterprise Linux 8", 12 | "release_date": "2022-11-08T00:00:00Z", 13 | "advisory": "RHSA-2022:7830", 14 | "package": "nodejs:14-8070020221020110846.bd1311ed", 15 | "cpe": "cpe:/a:redhat:enterprise_linux:8" 16 | }, 17 | { 18 | "product_name": "Red Hat Enterprise Linux 8.1 Update Services for SAP Solutions", 19 | "release_date": "2022-06-07T00:00:00Z", 20 | "advisory": "RHEA-2022:4925", 21 | "package": "nodejs:12-8010020220518102644.c27ad7f8", 22 | "cpe": "cpe:/a:redhat:rhel_e4s:8.1" 23 | }, 24 | { 25 | "product_name": "Red Hat Enterprise Linux 8.2 Extended Update Support", 26 | "release_date": "2022-06-28T00:00:00Z", 27 | "advisory": "RHEA-2022:5221", 28 | "package": "nodejs:12-8020020220523154454.4cda2c84", 29 | "cpe": "cpe:/a:redhat:rhel_eus:8.2" 30 | }, 31 | { 32 | "product_name": "Red Hat Enterprise Linux 8.4 Extended Update Support", 33 | "release_date": "2022-07-19T00:00:00Z", 34 | "advisory": "RHEA-2022:5615", 35 | "package": "nodejs:12-8040020220523155137.522a0ee4", 36 | "cpe": "cpe:/a:redhat:rhel_eus:8.4" 37 | }, 38 | { 39 | "product_name": "Red Hat Software Collections for Red Hat Enterprise Linux 7", 40 | "release_date": "2022-06-06T00:00:00Z", 41 | "advisory": "RHSA-2022:4914", 42 | "package": "rh-nodejs12-nodejs-0:12.22.12-2.el7", 43 | "cpe": "cpe:/a:redhat:rhel_software_collections:3::el7" 44 | }, 45 | { 46 | "product_name": "Red Hat Software Collections for Red Hat Enterprise Linux 7", 47 | "release_date": "2022-10-19T00:00:00Z", 48 | "advisory": "RHSA-2022:7044", 49 | "package": "rh-nodejs14-nodejs-0:14.20.1-2.el7", 50 | "cpe": "cpe:/a:redhat:rhel_software_collections:3::el7" 51 | } 52 | ], 53 | "package_state": [ 54 | { 55 | "product_name": "Red Hat Enterprise Linux 8", 56 | "fix_state": "Affected", 57 | "package_name": "nodejs:16/nodejs", 58 | "cpe": "cpe:/o:redhat:enterprise_linux:8" 59 | }, 60 | { 61 | "product_name": "Red Hat Enterprise Linux 9", 62 | "fix_state": "Not affected", 63 | "package_name": "nodejs", 64 | "cpe": "cpe:/o:redhat:enterprise_linux:9" 65 | }, 66 | { 67 | "product_name": "Red Hat Openshift Data Foundation 4", 68 | "fix_state": "Affected", 69 | "package_name": "nodejs", 70 | "cpe": "cpe:/a:redhat:openshift_data_foundation:4" 71 | }, 72 | { 73 | "product_name": "Red Hat Quay 3", 74 | "fix_state": "Will not fix", 75 | "package_name": "nodejs", 76 | "cpe": "cpe:/a:redhat:quay:3" 77 | } 78 | ], 79 | "threat_severity": "Low", 80 | "public_date": "2022-01-10T00:00:00Z", 81 | "bugzilla": { 82 | "description": "CVE-2022-21824 nodejs: Prototype pollution via console.table properties", 83 | "id": "2040862", 84 | "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2040862" 85 | }, 86 | "cvss": { 87 | "cvss_base_score": "", 88 | "cvss_scoring_vector": "", 89 | "status": "" 90 | }, 91 | "cvss3": { 92 | "cvss3_base_score": "8.2", 93 | "cvss3_scoring_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H", 94 | "status": "verified" 95 | }, 96 | "iava": "", 97 | "cwe": "CWE-915", 98 | "statement": "Red Hat Quay from version 3.4 consumes nodejs from RHEL, so security tracking is provided by the container health index on the customer portal [1]. Additionally there is no impact from this issue on Quay 3.3 and 3.2 because nodejs is only used at build time and is no longer shipped, starting with Quay 3.5 [2].\n[1] https://catalog.redhat.com/software/containers/quay/quay-rhel8/600e03aadd19c7786c43ae49?container-tabs=security\n[2] https://issues.redhat.com/browse/PROJQUAY-1409\nTherefore Quay component is marked as \"Will not fix\".", 99 | "acknowledgement": "", 100 | "name": "CVE-2022-21824", 101 | "document_distribution": "", 102 | "details": [ 103 | "Due to the formatting logic of the \"console.table()\" function it was not safe to allow user controlled input to be passed to the \"properties\" parameter while simultaneously passing a plain object with at least one property as the first parameter, which could be \"__proto__\". The prototype pollution has very limited control, in that it only allows an empty string to be assigned to numerical keys of the object prototype.Node.js \u003e= 12.22.9, \u003e= 14.18.3, \u003e= 16.13.2, and \u003e= 17.3.1 use a null protoype for the object these properties are being assigned to." 104 | ], 105 | "references": [ 106 | "https://nodejs.org/en/blog/vulnerability/jan-2022-security-releases/" 107 | ] 108 | } -------------------------------------------------------------------------------- /test/data/GHSA-vc2p-r46x-m3vx.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "GHSA-vc2p-r46x-m3vx", 3 | "summary": "Argument injection in lettre", 4 | "details": "### Impact\n\nAffected versions of lettre allowed argument injection to the sendmail command. It was possible, using forged to addresses, to pass arbitrary arguments to the sendmail executable.\n\nDepending on the implementation (original sendmail, postfix, exim, etc.) it could be possible in some cases to write email data into abritrary files (using sendmail's logging features).\n\n*NOTE*: This vulnerability only affects the sendmail transport. Others, including smtp, are not affected.\n\n### Fix\n\nThe flaw is corrected by modifying the executed command to stop parsing arguments before passing the destination addresses.\n\n### References\n\n* [RUSTSEC-2020-0069](https://rustsec.org/advisories/RUSTSEC-2020-0069.html)\n* [CVE-2020-28247](https://nvd.nist.gov/vuln/detail/CVE-2020-28247)", 5 | "aliases": [ 6 | "CVE-2020-28247", 7 | "RUSTSEC-2020-0069" 8 | ], 9 | "modified": "2023-11-08T04:03:24.160094Z", 10 | "published": "2021-08-25T20:56:48Z", 11 | "database_specific": { 12 | "nvd_published_at": null, 13 | "cwe_ids": [ 14 | "CWE-77" 15 | ], 16 | "severity": "MODERATE", 17 | "github_reviewed": true, 18 | "github_reviewed_at": "2021-08-18T20:59:57Z" 19 | }, 20 | "references": [ 21 | { 22 | "type": "WEB", 23 | "url": "https://github.com/lettre/lettre/security/advisories/GHSA-vc2p-r46x-m3vx" 24 | }, 25 | { 26 | "type": "ADVISORY", 27 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-28247" 28 | }, 29 | { 30 | "type": "WEB", 31 | "url": "https://github.com/RustSec/advisory-db/pull/478/files" 32 | }, 33 | { 34 | "type": "WEB", 35 | "url": "https://github.com/lettre/lettre/pull/508/commits/bbe7cc5381c5380b54fb8bbb4f77a3725917ff0b" 36 | }, 37 | { 38 | "type": "PACKAGE", 39 | "url": "https://github.com/lettre/lettre" 40 | }, 41 | { 42 | "type": "WEB", 43 | "url": "https://rustsec.org/advisories/RUSTSEC-2020-0069.html" 44 | } 45 | ], 46 | "affected": [ 47 | { 48 | "package": { 49 | "name": "lettre", 50 | "ecosystem": "crates.io", 51 | "purl": "pkg:cargo/lettre" 52 | }, 53 | "ranges": [ 54 | { 55 | "type": "SEMVER", 56 | "events": [ 57 | { 58 | "introduced": "0.9.0" 59 | }, 60 | { 61 | "fixed": "0.9.5" 62 | } 63 | ] 64 | } 65 | ], 66 | "ecosystem_specific": { 67 | "affected_functions": [ 68 | "lettre::sendmail::SendmailTransport::send", 69 | "lettre::transport::sendmail::SendmailTransport::send", 70 | "lettre::transport::sendmail::SendmailTransport::send_raw" 71 | ] 72 | }, 73 | "database_specific": { 74 | "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/08/GHSA-vc2p-r46x-m3vx/GHSA-vc2p-r46x-m3vx.json" 75 | } 76 | }, 77 | { 78 | "package": { 79 | "name": "lettre", 80 | "ecosystem": "crates.io", 81 | "purl": "pkg:cargo/lettre" 82 | }, 83 | "ranges": [ 84 | { 85 | "type": "SEMVER", 86 | "events": [ 87 | { 88 | "introduced": "0.8.0" 89 | }, 90 | { 91 | "fixed": "0.8.4" 92 | } 93 | ] 94 | } 95 | ], 96 | "ecosystem_specific": { 97 | "affected_functions": [ 98 | "lettre::sendmail::SendmailTransport::send", 99 | "lettre::transport::sendmail::SendmailTransport::send", 100 | "lettre::transport::sendmail::SendmailTransport::send_raw" 101 | ] 102 | }, 103 | "database_specific": { 104 | "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/08/GHSA-vc2p-r46x-m3vx/GHSA-vc2p-r46x-m3vx.json" 105 | } 106 | }, 107 | { 108 | "package": { 109 | "name": "lettre", 110 | "ecosystem": "crates.io", 111 | "purl": "pkg:cargo/lettre" 112 | }, 113 | "ranges": [ 114 | { 115 | "type": "SEMVER", 116 | "events": [ 117 | { 118 | "introduced": "0.7.0" 119 | }, 120 | { 121 | "fixed": "0.7.1" 122 | } 123 | ] 124 | } 125 | ], 126 | "ecosystem_specific": { 127 | "affected_functions": [ 128 | "lettre::sendmail::SendmailTransport::send", 129 | "lettre::transport::sendmail::SendmailTransport::send", 130 | "lettre::transport::sendmail::SendmailTransport::send_raw" 131 | ] 132 | }, 133 | "database_specific": { 134 | "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/08/GHSA-vc2p-r46x-m3vx/GHSA-vc2p-r46x-m3vx.json" 135 | } 136 | } 137 | ], 138 | "schema_version": "1.6.0", 139 | "severity": [ 140 | { 141 | "type": "CVSS_V3", 142 | "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N" 143 | } 144 | ] 145 | } -------------------------------------------------------------------------------- /contrib/cpe_research.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | import apsw 4 | import orjson 5 | from rich.console import Console 6 | from rich.live import Live 7 | from rich.table import Table 8 | 9 | from vdb.lib import KNOWN_PKG_TYPES, db6, CPE_FULL_REGEX 10 | from vdb.lib.cve_model import CVE, CVE1, tagger 11 | 12 | console = Console(markup=False, highlight=False, emoji=False) 13 | 14 | purl_proposal_cache = {} 15 | 16 | def get_cve_data(db_conn, index_hits: list[dict, Any]): 17 | """Get CVE data for the index results 18 | 19 | Args: 20 | db_conn: DB Connection or None to create a new one 21 | index_hits: Hits from one of the search methods 22 | search_str: Original search string used 23 | 24 | Returns: 25 | generator: generator for CVE data with original source data as a pydantic model 26 | """ 27 | if not db_conn: 28 | db_conn, _ = db6.get(read_only=True) 29 | for ahit in index_hits: 30 | results: apsw.Cursor = db_conn.execute( 31 | "SELECT distinct json_object('source', source_data) FROM cve_data WHERE cve_id = ? AND type = ? ORDER BY cve_id DESC;", 32 | (ahit[0], ahit[1]), 33 | ) 34 | for res in results: 35 | yield { 36 | "purl_prefix": ahit[-1], 37 | "source_data": ( 38 | CVE( 39 | root=CVE1.model_validate( 40 | orjson.loads(res[0])["source"], strict=False 41 | ) 42 | ) 43 | if res[0] 44 | else None 45 | ), 46 | } 47 | 48 | 49 | def propose_pseudo_purls() -> list: 50 | """Get a list of namespaces without a precise purl prefix and propose a pseudo purls""" 51 | db_conn, index_conn = db6.get(read_only=True) 52 | ptypes = KNOWN_PKG_TYPES 53 | # These vendors are causing noise and slow-downs 54 | ptypes.extend( 55 | [ 56 | "oracle", 57 | "microsoft", 58 | "adobe", 59 | "f5", 60 | "dell", 61 | "cisco", 62 | "symantec", 63 | "gigabyte", 64 | "mozilla", 65 | "wireshark", 66 | "schneider-electric", 67 | "ibm", 68 | "fujitsu", 69 | "apple", 70 | "netapp", 71 | "synology", 72 | "citrix", 73 | "juniper", 74 | "qnap", 75 | "tenable", 76 | ] 77 | ) 78 | raw_hits = index_conn.execute( 79 | f"""select distinct cve_id, type, namespace, name, purl_prefix from cve_index where type not in ({', '.join([f"'{p}'" for p in ptypes])})""" 80 | ) 81 | table = Table(title="Results", highlight=False, show_lines=True) 82 | table.add_column("PURL prefix") 83 | table.add_column("CPEs") 84 | table.add_column("References") 85 | table.add_column("Tags") 86 | with Live( 87 | table, console=console, refresh_per_second=4, vertical_overflow="visible" 88 | ): 89 | for ahit in raw_hits: 90 | data_list_gen = get_cve_data(db_conn, [ahit]) 91 | for data_list in data_list_gen: 92 | source_data: CVE1 = data_list["source_data"].root 93 | if not source_data.containers.cna.references: 94 | continue 95 | references = source_data.containers.cna.references.root 96 | ref_urls = [ 97 | str(a.url.root).lower() 98 | for a in references 99 | if "git" not in str(a.url.root).lower() 100 | ] 101 | if not ref_urls: 102 | continue 103 | purl_prefix = data_list["purl_prefix"] 104 | affected = source_data.containers.cna.affected.root 105 | cpes = ["\n".join([b.root for b in a.cpes]) for a in affected] 106 | generic_cpes = [ 107 | acpe for acpe in cpes if acpe.startswith("cpe:2.3:a:generic") 108 | ] 109 | tags = tagger.get_reference_tags(ref_urls) 110 | tags = set([a["tag"] for a in tags]) 111 | proposed_purls = [] 112 | for generic_cpe in generic_cpes: 113 | all_parts = CPE_FULL_REGEX.match(generic_cpe) 114 | proposed_purl = f"pkg:generic/{all_parts.group('package')}" 115 | version = all_parts.group("version") 116 | if version and version != "*": 117 | proposed_purl = f"{proposed_purl}@{version}" 118 | proposed_purls.append(proposed_purl) 119 | if proposed_purls: 120 | purl_proposal_cache[purl_prefix] = proposed_purls 121 | elif purl_proposal_cache.get(purl_prefix): 122 | proposed_purls = purl_proposal_cache[purl_prefix] 123 | table.add_row( 124 | purl_prefix + "\n" + "\n".join(proposed_purls), 125 | cpes[0], 126 | "\n".join(ref_urls), 127 | "\n".join(list(tags)), 128 | ) 129 | 130 | 131 | if __name__ == "__main__": 132 | propose_pseudo_purls() 133 | -------------------------------------------------------------------------------- /test/data/osv-npm-star-bug.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.4.0", 3 | "id": "GHSA-67hx-6x53-jw92", 4 | "modified": "2024-04-04T14:26:10Z", 5 | "published": "2023-10-16T13:55:36Z", 6 | "aliases": [ 7 | "CVE-2023-45133" 8 | ], 9 | "summary": "Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code", 10 | "details": "### Impact\n\nUsing Babel to compile code that was specifically crafted by an attacker can lead to arbitrary code execution during compilation, when using plugins that rely on the `path.evaluate()`or `path.evaluateTruthy()` internal Babel methods.\n\nKnown affected plugins are:\n- `@babel/plugin-transform-runtime`\n- `@babel/preset-env` when using its [`useBuiltIns`](https://babeljs.io/docs/babel-preset-env#usebuiltins) option\n- Any \"polyfill provider\" plugin that depends on `@babel/helper-define-polyfill-provider`, such as `babel-plugin-polyfill-corejs3`, `babel-plugin-polyfill-corejs2`, `babel-plugin-polyfill-es-shims`, `babel-plugin-polyfill-regenerator`\n\nNo other plugins under the `@babel/` namespace are impacted, but third-party plugins might be.\n\n**Users that only compile trusted code are not impacted.**\n\n### Patches\n\nThe vulnerability has been fixed in `@babel/traverse@7.23.2`.\n\nBabel 6 does not receive security fixes anymore (see [Babel's security policy](https://github.com/babel/babel/security/policy)), hence there is no patch planned for `babel-traverse@6`.\n\n### Workarounds\n\n- Upgrade `@babel/traverse` to v7.23.2 or higher. You can do this by deleting it from your package manager's lockfile and re-installing the dependencies. `@babel/core` >=7.23.2 will automatically pull in a non-vulnerable version.\n- If you cannot upgrade `@babel/traverse` and are using one of the affected packages mentioned above, upgrade them to their latest version to avoid triggering the vulnerable code path in affected `@babel/traverse` versions:\n - `@babel/plugin-transform-runtime` v7.23.2\n - `@babel/preset-env` v7.23.2\n - `@babel/helper-define-polyfill-provider` v0.4.3\n - `babel-plugin-polyfill-corejs2` v0.4.6\n - `babel-plugin-polyfill-corejs3` v0.8.5\n - `babel-plugin-polyfill-es-shims` v0.10.0\n - `babel-plugin-polyfill-regenerator` v0.5.3", 11 | "severity": [ 12 | { 13 | "type": "CVSS_V3", 14 | "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H" 15 | } 16 | ], 17 | "affected": [ 18 | { 19 | "package": { 20 | "ecosystem": "npm", 21 | "name": "@babel/traverse" 22 | }, 23 | "ranges": [ 24 | { 25 | "type": "ECOSYSTEM", 26 | "events": [ 27 | { 28 | "introduced": "0" 29 | }, 30 | { 31 | "fixed": "7.23.2" 32 | } 33 | ] 34 | } 35 | ] 36 | }, 37 | { 38 | "package": { 39 | "ecosystem": "npm", 40 | "name": "@babel/traverse" 41 | }, 42 | "ranges": [ 43 | { 44 | "type": "ECOSYSTEM", 45 | "events": [ 46 | { 47 | "introduced": "8.0.0-alpha.0" 48 | }, 49 | { 50 | "fixed": "8.0.0-alpha.4" 51 | } 52 | ] 53 | } 54 | ] 55 | }, 56 | { 57 | "package": { 58 | "ecosystem": "npm", 59 | "name": "babel-traverse" 60 | }, 61 | "ranges": [ 62 | { 63 | "type": "ECOSYSTEM", 64 | "events": [ 65 | { 66 | "introduced": "0" 67 | } 68 | ] 69 | } 70 | ], 71 | "database_specific": { 72 | "last_known_affected_version_range": "< 7.23.2" 73 | } 74 | } 75 | ], 76 | "references": [ 77 | { 78 | "type": "WEB", 79 | "url": "https://github.com/babel/babel/security/advisories/GHSA-67hx-6x53-jw92" 80 | }, 81 | { 82 | "type": "ADVISORY", 83 | "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-45133" 84 | }, 85 | { 86 | "type": "WEB", 87 | "url": "https://github.com/babel/babel/pull/16033" 88 | }, 89 | { 90 | "type": "WEB", 91 | "url": "https://github.com/babel/babel/commit/b13376b346946e3f62fc0848c1d2a23223314c82" 92 | }, 93 | { 94 | "type": "WEB", 95 | "url": "https://babeljs.io/blog/2023/10/16/cve-2023-45133" 96 | }, 97 | { 98 | "type": "PACKAGE", 99 | "url": "https://github.com/babel/babel" 100 | }, 101 | { 102 | "type": "WEB", 103 | "url": "https://github.com/babel/babel/releases/tag/v7.23.2" 104 | }, 105 | { 106 | "type": "WEB", 107 | "url": "https://github.com/babel/babel/releases/tag/v8.0.0-alpha.4" 108 | }, 109 | { 110 | "type": "WEB", 111 | "url": "https://lists.debian.org/debian-lts-announce/2023/10/msg00026.html" 112 | }, 113 | { 114 | "type": "WEB", 115 | "url": "https://www.debian.org/security/2023/dsa-5528" 116 | } 117 | ], 118 | "database_specific": { 119 | "cwe_ids": [ 120 | "CWE-184", 121 | "CWE-697" 122 | ], 123 | "severity": "CRITICAL", 124 | "github_reviewed": true, 125 | "github_reviewed_at": "2023-10-16T13:55:36Z", 126 | "nvd_published_at": "2023-10-12T17:15:09Z" 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /vdb/lib/cve_model/cvss_v3.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=C0115, C0103, C0301 2 | 3 | from __future__ import annotations 4 | 5 | from enum import Enum 6 | from typing import Annotated, Optional 7 | 8 | from pydantic import BaseModel, Field 9 | 10 | from vdb.lib.cve_model.common import ( 11 | AttackComplexityType, 12 | AttackVectorTypeModel, 13 | CiaRequirementType, 14 | CiaType, 15 | ConfidenceType, 16 | ExploitCodeMaturityType, 17 | ModifiedAttackComplexityType, 18 | ModifiedAttackVectorTypeModel, 19 | ModifiedCiaType, 20 | ModifiedPrivilegesRequiredType, 21 | ModifiedScopeType, 22 | ModifiedUserInteractionTypeModel, 23 | PrivilegesRequiredType, 24 | RemediationLevelType, 25 | ScopeType, 26 | ScoreTypeModel, 27 | SeverityType, 28 | UserInteractionTypeModel, 29 | ) 30 | 31 | 32 | class Version(Enum): 33 | field_3_1 = "3.1" 34 | 35 | 36 | class Version1Model(Enum): 37 | field_3_0 = "3.0" 38 | 39 | 40 | class Field1(BaseModel): 41 | version: Annotated[Version, Field(description="CVSS Version")] 42 | vectorString: Annotated[ 43 | str, 44 | Field( 45 | pattern="^CVSS:3[.]1/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$" 46 | ), 47 | ] 48 | attackVector: Optional[AttackVectorTypeModel] = None 49 | attackComplexity: Optional[AttackComplexityType] = None 50 | privilegesRequired: Optional[PrivilegesRequiredType] = None 51 | userInteraction: Optional[UserInteractionTypeModel] = None 52 | scope: Optional[ScopeType] = None 53 | confidentialityImpact: Optional[CiaType] = None 54 | integrityImpact: Optional[CiaType] = None 55 | availabilityImpact: Optional[CiaType] = None 56 | baseScore: ScoreTypeModel 57 | baseSeverity: SeverityType 58 | exploitCodeMaturity: Optional[ExploitCodeMaturityType] = None 59 | remediationLevel: Optional[RemediationLevelType] = None 60 | reportConfidence: Optional[ConfidenceType] = None 61 | temporalScore: Optional[ScoreTypeModel] = None 62 | temporalSeverity: Optional[SeverityType] = None 63 | confidentialityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 64 | integrityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 65 | availabilityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 66 | modifiedAttackVector: Optional[ModifiedAttackVectorTypeModel] = None 67 | modifiedAttackComplexity: Optional[ModifiedAttackComplexityType] = "NOT_DEFINED" 68 | modifiedPrivilegesRequired: Optional[ModifiedPrivilegesRequiredType] = "NOT_DEFINED" 69 | modifiedUserInteraction: Optional[ModifiedUserInteractionTypeModel] = None 70 | modifiedScope: Optional[ModifiedScopeType] = None 71 | modifiedConfidentialityImpact: Optional[ModifiedCiaType] = None 72 | modifiedIntegrityImpact: Optional[ModifiedCiaType] = None 73 | modifiedAvailabilityImpact: Optional[ModifiedCiaType] = None 74 | environmentalScore: Optional[ScoreTypeModel] = None 75 | environmentalSeverity: Optional[SeverityType] = None 76 | 77 | 78 | class Field0(BaseModel): 79 | version: Annotated[Version1Model, Field(description="CVSS Version")] 80 | vectorString: Annotated[ 81 | str, 82 | Field( 83 | pattern="^CVSS:3[.]0/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$" 84 | ), 85 | ] 86 | attackVector: Optional[AttackVectorTypeModel] = None 87 | attackComplexity: Optional[AttackComplexityType] = None 88 | privilegesRequired: Optional[PrivilegesRequiredType] = None 89 | userInteraction: Optional[UserInteractionTypeModel] = None 90 | scope: Optional[ScopeType] = None 91 | confidentialityImpact: Optional[CiaType] = None 92 | integrityImpact: Optional[CiaType] = None 93 | availabilityImpact: Optional[CiaType] = None 94 | baseScore: ScoreTypeModel 95 | baseSeverity: SeverityType 96 | exploitCodeMaturity: Optional[ExploitCodeMaturityType] = None 97 | remediationLevel: Optional[RemediationLevelType] = None 98 | reportConfidence: Optional[ConfidenceType] = None 99 | temporalScore: Optional[ScoreTypeModel] = None 100 | temporalSeverity: Optional[SeverityType] = None 101 | confidentialityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 102 | integrityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 103 | availabilityRequirement: Optional[CiaRequirementType] = "NOT_DEFINED" 104 | modifiedAttackVector: Optional[ModifiedAttackVectorTypeModel] = None 105 | modifiedAttackComplexity: Optional[ModifiedAttackComplexityType] = "NOT_DEFINED" 106 | modifiedPrivilegesRequired: Optional[ModifiedPrivilegesRequiredType] = "NOT_DEFINED" 107 | modifiedUserInteraction: Optional[ModifiedUserInteractionTypeModel] = None 108 | modifiedScope: Optional[ModifiedScopeType] = None 109 | modifiedConfidentialityImpact: Optional[ModifiedCiaType] = None 110 | modifiedIntegrityImpact: Optional[ModifiedCiaType] = None 111 | modifiedAvailabilityImpact: Optional[ModifiedCiaType] = None 112 | environmentalScore: Optional[ScoreTypeModel] = None 113 | environmentalSeverity: Optional[SeverityType] = None 114 | -------------------------------------------------------------------------------- /vdb/lib/custom.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Dict, List, Any, Generator 3 | 4 | try: 5 | import yaml 6 | except ImportError: 7 | yaml = None 8 | 9 | try: 10 | import tomllib 11 | except ImportError: 12 | try: 13 | import toml as tomllib 14 | except ImportError: 15 | tomllib = None 16 | 17 | from vdb.lib import utils 18 | from vdb.lib.cve_model import CVE 19 | 20 | 21 | class CustomSource: 22 | """ 23 | Source for loading custom vulnerability data strictly following CVE 5.2 schema 24 | from local files (JSON, YAML, TOML) for runtime overlay. 25 | """ 26 | 27 | def __init__(self, path: str): 28 | self.path = path 29 | 30 | def load_in_memory(self) -> List[Dict]: 31 | """ 32 | Load processed data into memory for runtime overlay search. 33 | """ 34 | results = [] 35 | if not os.path.exists(self.path): 36 | return results 37 | 38 | for item in self._yield_items(): 39 | results.append(item) 40 | 41 | return results 42 | 43 | def _yield_items(self) -> Generator[Dict, None, None]: 44 | """Generator that yields processed CVE items normalized for search""" 45 | for root, _, files in os.walk(self.path): 46 | for file in files: 47 | file_path = os.path.join(root, file) 48 | try: 49 | raw_data = self._parse_file(file_path) 50 | if not raw_data: 51 | continue 52 | 53 | items = raw_data if isinstance(raw_data, list) else [raw_data] 54 | 55 | for item in items: 56 | if "containers" in item: 57 | if ( 58 | "adp" in item["containers"] 59 | and "cna" not in item["containers"] 60 | ): 61 | item["containers"]["cna"] = None 62 | 63 | try: 64 | cve_obj = CVE.model_validate(item) 65 | except Exception as e: 66 | print(f"Schema validation failed for {file_path}: {e}") 67 | continue 68 | cve_record = cve_obj.root 69 | cve_id = ( 70 | cve_record.cveMetadata.cveId.root 71 | if hasattr(cve_record.cveMetadata.cveId, "root") 72 | else cve_record.cveMetadata.cveId 73 | ) 74 | # Process ADP 75 | if cve_record.containers.adp: 76 | for adp in cve_record.containers.adp: 77 | if adp.affected: 78 | for product in adp.affected.root: 79 | yield from self._process_product( 80 | cve_id, cve_obj, product 81 | ) 82 | # Process CNA 83 | if ( 84 | cve_record.containers.cna 85 | and cve_record.containers.cna.affected 86 | ): 87 | for product in cve_record.containers.cna.affected.root: 88 | yield from self._process_product( 89 | cve_id, cve_obj, product 90 | ) 91 | except Exception as e: 92 | print(f"Failed to process {file_path}: {e}") 93 | 94 | def _process_product(self, cve_id, cve_obj, product) -> Generator[Dict, None, None]: 95 | """Convert a Product object into an in-memory index row""" 96 | purl_obj = {} 97 | purl_prefix = "" 98 | 99 | if product.packageURL: 100 | p_url = ( 101 | product.packageURL.root 102 | if hasattr(product.packageURL, "root") 103 | else product.packageURL 104 | ) 105 | purl_obj = utils.parse_purl(str(p_url)) 106 | 107 | if purl_obj: 108 | ptype = purl_obj.get("type") 109 | namespace = purl_obj.get("namespace") 110 | name = purl_obj.get("name") 111 | purl_prefix = f"pkg:{ptype}/" 112 | if namespace: 113 | purl_prefix = f"{purl_prefix}{namespace.replace('@', '%40')}/" 114 | purl_prefix = f"{purl_prefix}{name}" 115 | 116 | if not purl_prefix: 117 | return 118 | 119 | vendor_for_vers = purl_obj.get("type", "generic") 120 | vers_str = "" 121 | if product.versions: 122 | vers_str = utils.to_purl_vers(vendor_for_vers, product.versions) 123 | 124 | fix_version = utils.get_unaffected(cve_obj, vers_str) 125 | 126 | yield { 127 | "cve_id": cve_id, 128 | "type": purl_obj.get("type", "custom"), 129 | "namespace": purl_obj.get("namespace", ""), 130 | "name": purl_obj.get("name", product.packageName or "unknown"), 131 | "source_data": cve_obj, 132 | "vers": vers_str, 133 | "purl_prefix": purl_prefix, 134 | "fix_version": fix_version, 135 | "override_data": None, 136 | } 137 | 138 | def _parse_file(self, file_path: str) -> Any: 139 | ext = file_path.split(".")[-1].lower() 140 | with open(file_path, "r", encoding="utf-8") as fp: 141 | content = fp.read() 142 | if ext == "json": 143 | return utils.load(content) 144 | elif ext in ("yaml", "yml") and yaml: 145 | return yaml.safe_load(content) 146 | elif ext == "toml" and tomllib: 147 | return tomllib.loads(content) 148 | return None 149 | -------------------------------------------------------------------------------- /data/imports/cvss/cvss-v2.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": [ 3 | "Copyright (c) 2017, FIRST.ORG, INC.", 4 | "All rights reserved.", 5 | "", 6 | "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the ", 7 | "following conditions are met:", 8 | "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following ", 9 | " disclaimer.", 10 | "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the ", 11 | " following disclaimer in the documentation and/or other materials provided with the distribution.", 12 | "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote ", 13 | " products derived from this software without specific prior written permission.", 14 | "", 15 | "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, ", 16 | "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ", 17 | "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ", 18 | "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ", 19 | "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ", 20 | "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ", 21 | "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 22 | ], 23 | 24 | "$schema": "http://json-schema.org/draft-04/schema#", 25 | "title": "JSON Schema for Common Vulnerability Scoring System version 2.0", 26 | "id": "https://www.first.org/cvss/cvss-v2.0.json?20170531", 27 | "type": "object", 28 | "definitions": { 29 | "accessVectorType": { 30 | "type": "string", 31 | "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL" ] 32 | }, 33 | "accessComplexityType": { 34 | "type": "string", 35 | "enum": [ "HIGH", "MEDIUM", "LOW" ] 36 | }, 37 | "authenticationType": { 38 | "type": "string", 39 | "enum": [ "MULTIPLE", "SINGLE", "NONE" ] 40 | }, 41 | "ciaType": { 42 | "type": "string", 43 | "enum": [ "NONE", "PARTIAL", "COMPLETE" ] 44 | }, 45 | "exploitabilityType": { 46 | "type": "string", 47 | "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] 48 | }, 49 | "remediationLevelType": { 50 | "type": "string", 51 | "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] 52 | }, 53 | "reportConfidenceType": { 54 | "type": "string", 55 | "enum": [ "UNCONFIRMED", "UNCORROBORATED", "CONFIRMED", "NOT_DEFINED" ] 56 | }, 57 | "collateralDamagePotentialType": { 58 | "type": "string", 59 | "enum": [ "NONE", "LOW", "LOW_MEDIUM", "MEDIUM_HIGH", "HIGH", "NOT_DEFINED" ] 60 | }, 61 | "targetDistributionType": { 62 | "type": "string", 63 | "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] 64 | }, 65 | "ciaRequirementType": { 66 | "type": "string", 67 | "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] 68 | }, 69 | "scoreType": { 70 | "type": "number", 71 | "minimum": 0, 72 | "maximum": 10 73 | } 74 | }, 75 | "properties": { 76 | "version": { 77 | "description": "CVSS Version", 78 | "type": "string", 79 | "enum": [ "2.0" ] 80 | }, 81 | "vectorString": { 82 | "type": "string", 83 | "pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$" 84 | }, 85 | "accessVector": { "$ref": "#/definitions/accessVectorType" }, 86 | "accessComplexity": { "$ref": "#/definitions/accessComplexityType" }, 87 | "authentication": { "$ref": "#/definitions/authenticationType" }, 88 | "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, 89 | "integrityImpact": { "$ref": "#/definitions/ciaType" }, 90 | "availabilityImpact": { "$ref": "#/definitions/ciaType" }, 91 | "baseScore": { "$ref": "#/definitions/scoreType" }, 92 | "exploitability": { "$ref": "#/definitions/exploitabilityType" }, 93 | "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, 94 | "reportConfidence": { "$ref": "#/definitions/reportConfidenceType" }, 95 | "temporalScore": { "$ref": "#/definitions/scoreType" }, 96 | "collateralDamagePotential": { "$ref": "#/definitions/collateralDamagePotentialType" }, 97 | "targetDistribution": { "$ref": "#/definitions/targetDistributionType" }, 98 | "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 99 | "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 100 | "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, 101 | "environmentalScore": { "$ref": "#/definitions/scoreType" } 102 | }, 103 | "required": [ "version", "vectorString", "baseScore" ] 104 | } 105 | -------------------------------------------------------------------------------- /vdb/lib/db6.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta, timezone 2 | import json 3 | import os 4 | import sys 5 | import tempfile 6 | import apsw 7 | 8 | from vdb.lib import config 9 | from vdb.lib.utils import vers_compare 10 | 11 | db_conn: apsw.Connection = None 12 | index_conn: apsw.Connection = None 13 | tables_created = False 14 | DB_FILE_SEP = "///" if sys.platform == "win32" else "//" 15 | 16 | 17 | def ensure_schemas(db_conn_obj: apsw.Connection, index_conn_obj: apsw.Connection): 18 | # Use temp files to reduce memory usage during VACCUM 19 | # See issue #203 20 | temp_store_dir = os.getenv("VDB_TEMP_DIR", tempfile.mkdtemp(prefix="vdb-temp")) 21 | """Create the sqlite tables and indexes in case they don't exist""" 22 | db_conn_obj.execute( 23 | "CREATE TABLE if not exists cve_data(cve_id TEXT NOT NULL, type TEXT NOT NULL, namespace TEXT, name TEXT NOT NULL, source_data BLOB NOT NULL, override_data BLOB, source_data_hash TEXT NOT NULL, vers TEXT NOT NULL, purl_prefix TEXT NOT NULL);" 24 | ) 25 | db_conn_obj.pragma("synchronous", "OFF") 26 | db_conn_obj.pragma("journal_mode", "MEMORY") 27 | if os.access(temp_store_dir, os.W_OK): 28 | db_conn_obj.pragma("temp_store", "FILE") 29 | db_conn_obj.pragma("temp_store_directory", temp_store_dir) 30 | else: 31 | db_conn_obj.pragma("temp_store", "MEMORY") 32 | index_conn_obj.execute( 33 | "CREATE TABLE if not exists cve_index(cve_id TEXT NOT NULL, type TEXT NOT NULL, namespace TEXT, name TEXT NOT NULL, vers TEXT NOT NULL, purl_prefix TEXT NOT NULL);" 34 | ) 35 | index_conn_obj.pragma("synchronous", "OFF") 36 | index_conn_obj.pragma("journal_mode", "MEMORY") 37 | if os.access(temp_store_dir, os.W_OK): 38 | index_conn_obj.pragma("temp_store", "FILE") 39 | index_conn_obj.pragma("temp_store_directory", temp_store_dir) 40 | else: 41 | index_conn_obj.pragma("temp_store", "MEMORY") 42 | 43 | 44 | def get( 45 | db_file: str = config.VDB_BIN_FILE, 46 | index_file: str = config.VDB_BIN_INDEX, 47 | read_only=False, 48 | ) -> (apsw.Connection, apsw.Connection): 49 | """Gets the connection to the index and the data databases. Raises apsw.CantOpenError if the database is not available.""" 50 | global db_conn, index_conn, tables_created 51 | if not db_file.startswith("file:") and db_file != ":memory:": 52 | db_file = f"file:{DB_FILE_SEP}{os.path.abspath(db_file)}" 53 | if not index_file.startswith("file:") and index_file != ":memory:": 54 | index_file = f"file:{DB_FILE_SEP}{os.path.abspath(index_file)}" 55 | rw_flags = ( 56 | apsw.SQLITE_OPEN_URI 57 | | apsw.SQLITE_OPEN_NOFOLLOW 58 | | apsw.SQLITE_OPEN_CREATE 59 | | apsw.SQLITE_OPEN_READWRITE 60 | ) 61 | ro_flags = ( 62 | apsw.SQLITE_OPEN_URI | apsw.SQLITE_OPEN_NOFOLLOW | apsw.SQLITE_OPEN_READONLY 63 | ) 64 | # To avoid apsw.CantOpenError, we support readonly mode only if the db exists 65 | flags = ( 66 | ro_flags 67 | if read_only and os.path.exists(db_file) and os.path.exists(index_file) 68 | else rw_flags 69 | ) 70 | if not db_conn: 71 | db_conn = apsw.Connection(db_file, flags=flags) 72 | if not index_conn: 73 | index_conn = apsw.Connection(index_file, flags=flags) 74 | index_conn.createscalarfunction( 75 | "vers_compare", vers_compare, deterministic=True 76 | ) 77 | if not tables_created: 78 | ensure_schemas(db_conn, index_conn) 79 | tables_created = True 80 | return db_conn, index_conn 81 | 82 | 83 | def stats(): 84 | cve_data_count = 0 85 | res = db_conn.execute("SELECT count(*) FROM cve_data").fetchone() 86 | if res: 87 | cve_data_count = res[0] 88 | cve_index_count = 0 89 | res = index_conn.execute("SELECT count(*) FROM cve_index").fetchone() 90 | if res: 91 | cve_index_count = res[0] 92 | return cve_data_count, cve_index_count 93 | 94 | 95 | def clear_all(): 96 | if db_conn: 97 | db_conn.execute("DELETE FROM cve_data;") 98 | if index_conn: 99 | index_conn.execute("DELETE FROM cve_index;") 100 | 101 | 102 | def optimize_and_close_all(): 103 | """ 104 | Safely close the connections by creating indexes and vacuuming if needed. 105 | """ 106 | if db_conn: 107 | db_conn.execute( 108 | "CREATE INDEX if not exists idx1 on cve_data(cve_id, vers, purl_prefix);" 109 | ) 110 | db_conn.execute("VACUUM;") 111 | db_conn.close() 112 | if index_conn: 113 | index_conn.execute("CREATE INDEX if not exists cidx1 on cve_index(cve_id);") 114 | index_conn.execute( 115 | "CREATE INDEX if not exists cidx2 on cve_index(type, namespace, name);" 116 | ) 117 | index_conn.execute("CREATE INDEX if not exists cidx3 on cve_index(type, name);") 118 | index_conn.execute( 119 | "CREATE INDEX if not exists cidx4 on cve_index(namespace, name);" 120 | ) 121 | index_conn.execute( 122 | "CREATE INDEX if not exists cidx5 on cve_index(purl_prefix);" 123 | ) 124 | index_conn.execute("VACUUM;") 125 | index_conn.close() 126 | 127 | 128 | def get_db_file_metadata(): 129 | """ 130 | Returns the metadata for the cached vdb files. 131 | """ 132 | if not os.path.exists(config.VDB_METADATA_FILE): 133 | return None 134 | with open(config.VDB_METADATA_FILE, encoding="utf-8") as meta_file: 135 | return json.load(meta_file) 136 | 137 | 138 | def needs_update(days=1, hours=0, minutes=0, seconds=0, default_status=False): 139 | """ 140 | Determines if the db needs to be updated based on creation time 141 | """ 142 | db_metadata = get_db_file_metadata() 143 | if not db_metadata or not db_metadata.get("created_utc"): 144 | return default_status 145 | current_time = datetime.now(tz=timezone.utc) 146 | created_time = datetime.fromisoformat(db_metadata["created_utc"]) 147 | diff = current_time - created_time 148 | return diff > timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) 149 | -------------------------------------------------------------------------------- /test/data/CVE-2022-32081.json: -------------------------------------------------------------------------------- 1 | { 2 | "PublicDateAtUSN": "2022-07-01T20:15:00Z", 3 | "CRD": "0001-01-01T00:00:00Z", 4 | "Candidate": "CVE-2022-32081", 5 | "PublicDate": "2022-07-01T20:15:00Z", 6 | "References": [ 7 | "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-32081", 8 | "https://jira.mariadb.org/browse/MDEV-26420", 9 | "https://ubuntu.com/security/notices/USN-5739-1" 10 | ], 11 | "Description": "MariaDB v10.4 to v10.7 was discovered to contain an use-after-poison in prepare_inplace_add_virtual at /storage/innobase/handler/handler0alter.cc.", 12 | "UbuntuDescription": "", 13 | "Notes": null, 14 | "Bugs": null, 15 | "Priority": "medium", 16 | "DiscoveredBy": "", 17 | "AssignedTo": "", 18 | "Patches": { 19 | "mariadb-10.0": { 20 | "bionic": { 21 | "Status": "DNE", 22 | "Note": "" 23 | }, 24 | "devel": { 25 | "Status": "DNE", 26 | "Note": "" 27 | }, 28 | "focal": { 29 | "Status": "DNE", 30 | "Note": "" 31 | }, 32 | "impish": { 33 | "Status": "DNE", 34 | "Note": "" 35 | }, 36 | "jammy": { 37 | "Status": "DNE", 38 | "Note": "" 39 | }, 40 | "kinetic": { 41 | "Status": "DNE", 42 | "Note": "" 43 | }, 44 | "trusty": { 45 | "Status": "DNE", 46 | "Note": "" 47 | }, 48 | "upstream": { 49 | "Status": "needs-triage", 50 | "Note": "" 51 | }, 52 | "xenial": { 53 | "Status": "ignored", 54 | "Note": "end of standard support, was needs-triage" 55 | } 56 | }, 57 | "mariadb-10.1": { 58 | "bionic": { 59 | "Status": "needs-triage", 60 | "Note": "" 61 | }, 62 | "devel": { 63 | "Status": "DNE", 64 | "Note": "" 65 | }, 66 | "focal": { 67 | "Status": "DNE", 68 | "Note": "" 69 | }, 70 | "impish": { 71 | "Status": "DNE", 72 | "Note": "" 73 | }, 74 | "jammy": { 75 | "Status": "DNE", 76 | "Note": "" 77 | }, 78 | "kinetic": { 79 | "Status": "DNE", 80 | "Note": "" 81 | }, 82 | "trusty": { 83 | "Status": "DNE", 84 | "Note": "" 85 | }, 86 | "upstream": { 87 | "Status": "needs-triage", 88 | "Note": "" 89 | }, 90 | "xenial": { 91 | "Status": "DNE", 92 | "Note": "" 93 | } 94 | }, 95 | "mariadb-10.3": { 96 | "bionic": { 97 | "Status": "DNE", 98 | "Note": "" 99 | }, 100 | "devel": { 101 | "Status": "DNE", 102 | "Note": "" 103 | }, 104 | "focal": { 105 | "Status": "released", 106 | "Note": "1:10.3.37-0ubuntu0.20.04.1" 107 | }, 108 | "impish": { 109 | "Status": "DNE", 110 | "Note": "" 111 | }, 112 | "jammy": { 113 | "Status": "DNE", 114 | "Note": "" 115 | }, 116 | "kinetic": { 117 | "Status": "DNE", 118 | "Note": "" 119 | }, 120 | "trusty": { 121 | "Status": "DNE", 122 | "Note": "" 123 | }, 124 | "upstream": { 125 | "Status": "needs-triage", 126 | "Note": "" 127 | }, 128 | "xenial": { 129 | "Status": "DNE", 130 | "Note": "" 131 | } 132 | }, 133 | "mariadb-10.5": { 134 | "bionic": { 135 | "Status": "DNE", 136 | "Note": "" 137 | }, 138 | "devel": { 139 | "Status": "DNE", 140 | "Note": "" 141 | }, 142 | "focal": { 143 | "Status": "DNE", 144 | "Note": "" 145 | }, 146 | "impish": { 147 | "Status": "ignored", 148 | "Note": "reached end-of-life" 149 | }, 150 | "jammy": { 151 | "Status": "DNE", 152 | "Note": "" 153 | }, 154 | "kinetic": { 155 | "Status": "DNE", 156 | "Note": "" 157 | }, 158 | "trusty": { 159 | "Status": "DNE", 160 | "Note": "" 161 | }, 162 | "upstream": { 163 | "Status": "needs-triage", 164 | "Note": "" 165 | }, 166 | "xenial": { 167 | "Status": "DNE", 168 | "Note": "" 169 | } 170 | }, 171 | "mariadb-10.6": { 172 | "bionic": { 173 | "Status": "DNE", 174 | "Note": "" 175 | }, 176 | "devel": { 177 | "Status": "not-affected", 178 | "Note": "1:10.6.9-1" 179 | }, 180 | "focal": { 181 | "Status": "DNE", 182 | "Note": "" 183 | }, 184 | "impish": { 185 | "Status": "DNE", 186 | "Note": "" 187 | }, 188 | "jammy": { 189 | "Status": "released", 190 | "Note": "1:10.6.11-0ubuntu0.22.04.1" 191 | }, 192 | "kinetic": { 193 | "Status": "released", 194 | "Note": "1:10.6.9-1" 195 | }, 196 | "trusty": { 197 | "Status": "DNE", 198 | "Note": "" 199 | }, 200 | "upstream": { 201 | "Status": "needs-triage", 202 | "Note": "" 203 | }, 204 | "xenial": { 205 | "Status": "DNE", 206 | "Note": "" 207 | } 208 | }, 209 | "mariadb-5.5": { 210 | "bionic": { 211 | "Status": "DNE", 212 | "Note": "" 213 | }, 214 | "devel": { 215 | "Status": "DNE", 216 | "Note": "" 217 | }, 218 | "focal": { 219 | "Status": "DNE", 220 | "Note": "" 221 | }, 222 | "impish": { 223 | "Status": "DNE", 224 | "Note": "" 225 | }, 226 | "jammy": { 227 | "Status": "DNE", 228 | "Note": "" 229 | }, 230 | "kinetic": { 231 | "Status": "DNE", 232 | "Note": "" 233 | }, 234 | "trusty": { 235 | "Status": "ignored", 236 | "Note": "end of standard support, was needs-triage" 237 | }, 238 | "upstream": { 239 | "Status": "needs-triage", 240 | "Note": "" 241 | }, 242 | "xenial": { 243 | "Status": "DNE", 244 | "Note": "" 245 | } 246 | } 247 | }, 248 | "UpstreamLinks": {} 249 | } -------------------------------------------------------------------------------- /test/data/ALAS2022-2022-207.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "ALAS2022-2022-207", 3 | "title": "Amazon Linux 2022 - ALAS2022-2022-207: Medium priority package update for gnupg2", 4 | "issued": { 5 | "date": "2022-11-01 21:25" 6 | }, 7 | "updated": { 8 | "date": "2022-11-01 21:25" 9 | }, 10 | "severity": "Medium", 11 | "description": "Package updates are available for Amazon Linux 2022 that fix the following vulnerabilities:\nCVE-2022-34903:\n\tA vulnerability was found in GnuPG. This issue occurs due to an escape detection loop at the write_status_text_and_buffer() function in g10/cpr.c. This flaw allows a malicious actor to bypass access control.\n", 12 | "packages": [ 13 | { 14 | "name": "gnupg2-smime-debuginfo", 15 | "epoch": "0", 16 | "version": "2.3.7", 17 | "release": "1.amzn2022.0.2", 18 | "arch": "x86_64", 19 | "filename": "Packages/gnupg2-smime-debuginfo-2.3.7-1.amzn2022.0.2.x86_64.rpm" 20 | }, 21 | { 22 | "name": "gnupg2-minimal", 23 | "epoch": "0", 24 | "version": "2.3.7", 25 | "release": "1.amzn2022.0.2", 26 | "arch": "x86_64", 27 | "filename": "Packages/gnupg2-minimal-2.3.7-1.amzn2022.0.2.x86_64.rpm" 28 | }, 29 | { 30 | "name": "gnupg2-minimal-debuginfo", 31 | "epoch": "0", 32 | "version": "2.3.7", 33 | "release": "1.amzn2022.0.2", 34 | "arch": "x86_64", 35 | "filename": "Packages/gnupg2-minimal-debuginfo-2.3.7-1.amzn2022.0.2.x86_64.rpm" 36 | }, 37 | { 38 | "name": "gnupg2-smime", 39 | "epoch": "0", 40 | "version": "2.3.7", 41 | "release": "1.amzn2022.0.2", 42 | "arch": "x86_64", 43 | "filename": "Packages/gnupg2-smime-2.3.7-1.amzn2022.0.2.x86_64.rpm" 44 | }, 45 | { 46 | "name": "gnupg2-debugsource", 47 | "epoch": "0", 48 | "version": "2.3.7", 49 | "release": "1.amzn2022.0.2", 50 | "arch": "x86_64", 51 | "filename": "Packages/gnupg2-debugsource-2.3.7-1.amzn2022.0.2.x86_64.rpm" 52 | }, 53 | { 54 | "name": "gnupg2", 55 | "epoch": "0", 56 | "version": "2.3.7", 57 | "release": "1.amzn2022.0.2", 58 | "arch": "x86_64", 59 | "filename": "Packages/gnupg2-2.3.7-1.amzn2022.0.2.x86_64.rpm" 60 | }, 61 | { 62 | "name": "gnupg2-debuginfo", 63 | "epoch": "0", 64 | "version": "2.3.7", 65 | "release": "1.amzn2022.0.2", 66 | "arch": "x86_64", 67 | "filename": "Packages/gnupg2-debuginfo-2.3.7-1.amzn2022.0.2.x86_64.rpm" 68 | }, 69 | { 70 | "name": "gnupg2-minimal-debuginfo", 71 | "epoch": "0", 72 | "version": "2.3.7", 73 | "release": "1.amzn2022.0.2", 74 | "arch": "i686", 75 | "filename": "Packages/gnupg2-minimal-debuginfo-2.3.7-1.amzn2022.0.2.i686.rpm" 76 | }, 77 | { 78 | "name": "gnupg2-debuginfo", 79 | "epoch": "0", 80 | "version": "2.3.7", 81 | "release": "1.amzn2022.0.2", 82 | "arch": "i686", 83 | "filename": "Packages/gnupg2-debuginfo-2.3.7-1.amzn2022.0.2.i686.rpm" 84 | }, 85 | { 86 | "name": "gnupg2-debugsource", 87 | "epoch": "0", 88 | "version": "2.3.7", 89 | "release": "1.amzn2022.0.2", 90 | "arch": "i686", 91 | "filename": "Packages/gnupg2-debugsource-2.3.7-1.amzn2022.0.2.i686.rpm" 92 | }, 93 | { 94 | "name": "gnupg2", 95 | "epoch": "0", 96 | "version": "2.3.7", 97 | "release": "1.amzn2022.0.2", 98 | "arch": "i686", 99 | "filename": "Packages/gnupg2-2.3.7-1.amzn2022.0.2.i686.rpm" 100 | }, 101 | { 102 | "name": "gnupg2-smime-debuginfo", 103 | "epoch": "0", 104 | "version": "2.3.7", 105 | "release": "1.amzn2022.0.2", 106 | "arch": "i686", 107 | "filename": "Packages/gnupg2-smime-debuginfo-2.3.7-1.amzn2022.0.2.i686.rpm" 108 | }, 109 | { 110 | "name": "gnupg2-minimal", 111 | "epoch": "0", 112 | "version": "2.3.7", 113 | "release": "1.amzn2022.0.2", 114 | "arch": "i686", 115 | "filename": "Packages/gnupg2-minimal-2.3.7-1.amzn2022.0.2.i686.rpm" 116 | }, 117 | { 118 | "name": "gnupg2-smime", 119 | "epoch": "0", 120 | "version": "2.3.7", 121 | "release": "1.amzn2022.0.2", 122 | "arch": "i686", 123 | "filename": "Packages/gnupg2-smime-2.3.7-1.amzn2022.0.2.i686.rpm" 124 | }, 125 | { 126 | "name": "gnupg2-minimal-debuginfo", 127 | "epoch": "0", 128 | "version": "2.3.7", 129 | "release": "1.amzn2022.0.2", 130 | "arch": "aarch64", 131 | "filename": "Packages/gnupg2-minimal-debuginfo-2.3.7-1.amzn2022.0.2.aarch64.rpm" 132 | }, 133 | { 134 | "name": "gnupg2-minimal", 135 | "epoch": "0", 136 | "version": "2.3.7", 137 | "release": "1.amzn2022.0.2", 138 | "arch": "aarch64", 139 | "filename": "Packages/gnupg2-minimal-2.3.7-1.amzn2022.0.2.aarch64.rpm" 140 | }, 141 | { 142 | "name": "gnupg2-smime-debuginfo", 143 | "epoch": "0", 144 | "version": "2.3.7", 145 | "release": "1.amzn2022.0.2", 146 | "arch": "aarch64", 147 | "filename": "Packages/gnupg2-smime-debuginfo-2.3.7-1.amzn2022.0.2.aarch64.rpm" 148 | }, 149 | { 150 | "name": "gnupg2-smime", 151 | "epoch": "0", 152 | "version": "2.3.7", 153 | "release": "1.amzn2022.0.2", 154 | "arch": "aarch64", 155 | "filename": "Packages/gnupg2-smime-2.3.7-1.amzn2022.0.2.aarch64.rpm" 156 | }, 157 | { 158 | "name": "gnupg2-debuginfo", 159 | "epoch": "0", 160 | "version": "2.3.7", 161 | "release": "1.amzn2022.0.2", 162 | "arch": "aarch64", 163 | "filename": "Packages/gnupg2-debuginfo-2.3.7-1.amzn2022.0.2.aarch64.rpm" 164 | }, 165 | { 166 | "name": "gnupg2-debugsource", 167 | "epoch": "0", 168 | "version": "2.3.7", 169 | "release": "1.amzn2022.0.2", 170 | "arch": "aarch64", 171 | "filename": "Packages/gnupg2-debugsource-2.3.7-1.amzn2022.0.2.aarch64.rpm" 172 | }, 173 | { 174 | "name": "gnupg2", 175 | "epoch": "0", 176 | "version": "2.3.7", 177 | "release": "1.amzn2022.0.2", 178 | "arch": "aarch64", 179 | "filename": "Packages/gnupg2-2.3.7-1.amzn2022.0.2.aarch64.rpm" 180 | } 181 | ], 182 | "references": [ 183 | { 184 | "href": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-34903", 185 | "id": "CVE-2022-34903", 186 | "type": "cve" 187 | } 188 | ], 189 | "cveids": [ 190 | "CVE-2022-34903" 191 | ] 192 | } --------------------------------------------------------------------------------