VulnCheck has some new, free API endpoints for the cybersecurity community.
Two extremely useful ones are for their extended version of CISA’s KEV, and an in-situ replacement for NVD’s sad excuse for an API and soon-to-be-removed JSON feeds.
There are two ways to work with these APIs. One is retrieve a “backup” of the entire dataset as a ZIP file, and the other is to use the API to retrieve individual CVEs from each “index”.
You’ll need a free API key from VulnCheck to use these APIs.
All code shown makes the assumption that you’ve stored your API key in an environment variable named VULNCHECK_API_KEY
.
After the curl
examples, there’s a section on a small Golang CLI I made to make it easier to get combined extended KEV and NVDv2 CVE information in one CLI call for a given CVE.
Backups
Retrieving the complete dataset is a multi-step process. First you make a call to the specific API endpoint for each index to backup. That returns some JSON with a temporary, AWS pre-signed URL (a method to grant temporary access to files stored in AWS S3) to download the ZIP file. Then you download the ZIP file, and finally you extract the contents of the ZIP file into a directory. The output is different for the NVDv2 and extended KEV indexes, but the core process is the same.
NVDv2
Here’s a curl
idiom for the NVDv2 index backup. The result is a directory of uncompressed JSON that’s in the same format as the NVDv2 JSON feeds.
# Grab the temporary AWS pre-signed URL for the NVDv2 index and then download the ZIP file.
curl \
--silent \
--output vcnvd2.zip --url "$(
curl \
--silent \
--cookie "token=${VULNCHECK_API_KEY}" \
--header 'Accept: application/json' \
--url "https://api.vulncheck.com/v3/backup/nist-nvd2" | jq -r '.data[].url'
)"
rm -rf ./nvd2
# unzip it
unzip -q -o -d ./nvd2 vcnvd2.zip
# uncompress the JSON files
ls ./nvd2/*gz | xargs gunzip
tree ./nvd2
./nvd2
├── nvdcve-2.0-000.json
├── nvdcve-2.0-001.json
├── nvdcve-2.0-002.json
├── nvdcve-2.0-003.json
├── nvdcve-2.0-004.json
├── nvdcve-2.0-005.json
├── nvdcve-2.0-006.json
├── nvdcve-2.0-007.json
├── nvdcve-2.0-008.json
├── nvdcve-2.0-009.json
├── nvdcve-2.0-010.json
├── nvdcve-2.0-011.json
├── nvdcve-2.0-012.json
├── nvdcve-2.0-013.json
├── nvdcve-2.0-014.json
├── nvdcve-2.0-015.json
├── nvdcve-2.0-016.json
├── nvdcve-2.0-017.json
├── nvdcve-2.0-018.json
├── nvdcve-2.0-019.json
├── nvdcve-2.0-020.json
├── nvdcve-2.0-021.json
├── nvdcve-2.0-022.json
├── nvdcve-2.0-023.json
├── nvdcve-2.0-024.json
├── nvdcve-2.0-025.json
├── nvdcve-2.0-026.json
├── nvdcve-2.0-027.json
├── nvdcve-2.0-028.json
├── nvdcve-2.0-029.json
├── nvdcve-2.0-030.json
├── nvdcve-2.0-031.json
├── nvdcve-2.0-032.json
├── nvdcve-2.0-033.json
├── nvdcve-2.0-034.json
├── nvdcve-2.0-035.json
├── nvdcve-2.0-036.json
├── nvdcve-2.0-037.json
├── nvdcve-2.0-038.json
├── nvdcve-2.0-039.json
├── nvdcve-2.0-040.json
├── nvdcve-2.0-041.json
├── nvdcve-2.0-042.json
├── nvdcve-2.0-043.json
├── nvdcve-2.0-044.json
├── nvdcve-2.0-045.json
├── nvdcve-2.0-046.json
├── nvdcve-2.0-047.json
├── nvdcve-2.0-048.json
├── nvdcve-2.0-049.json
├── nvdcve-2.0-050.json
├── nvdcve-2.0-051.json
├── nvdcve-2.0-052.json
├── nvdcve-2.0-053.json
├── nvdcve-2.0-054.json
├── nvdcve-2.0-055.json
├── nvdcve-2.0-056.json
├── nvdcve-2.0-057.json
├── nvdcve-2.0-058.json
├── nvdcve-2.0-059.json
├── nvdcve-2.0-060.json
├── nvdcve-2.0-061.json
├── nvdcve-2.0-062.json
├── nvdcve-2.0-063.json
├── nvdcve-2.0-064.json
├── nvdcve-2.0-065.json
├── nvdcve-2.0-066.json
├── nvdcve-2.0-067.json
├── nvdcve-2.0-068.json
├── nvdcve-2.0-069.json
├── nvdcve-2.0-070.json
├── nvdcve-2.0-071.json
├── nvdcve-2.0-072.json
├── nvdcve-2.0-073.json
├── nvdcve-2.0-074.json
├── nvdcve-2.0-075.json
├── nvdcve-2.0-076.json
├── nvdcve-2.0-077.json
├── nvdcve-2.0-078.json
├── nvdcve-2.0-079.json
├── nvdcve-2.0-080.json
├── nvdcve-2.0-081.json
├── nvdcve-2.0-082.json
├── nvdcve-2.0-083.json
├── nvdcve-2.0-084.json
├── nvdcve-2.0-085.json
├── nvdcve-2.0-086.json
├── nvdcve-2.0-087.json
├── nvdcve-2.0-088.json
├── nvdcve-2.0-089.json
├── nvdcve-2.0-090.json
├── nvdcve-2.0-091.json
├── nvdcve-2.0-092.json
├── nvdcve-2.0-093.json
├── nvdcve-2.0-094.json
├── nvdcve-2.0-095.json
├── nvdcve-2.0-096.json
├── nvdcve-2.0-097.json
├── nvdcve-2.0-098.json
├── nvdcve-2.0-099.json
├── nvdcve-2.0-100.json
├── nvdcve-2.0-101.json
├── nvdcve-2.0-102.json
├── nvdcve-2.0-103.json
├── nvdcve-2.0-104.json
├── nvdcve-2.0-105.json
├── nvdcve-2.0-106.json
├── nvdcve-2.0-107.json
├── nvdcve-2.0-108.json
├── nvdcve-2.0-109.json
├── nvdcve-2.0-110.json
├── nvdcve-2.0-111.json
├── nvdcve-2.0-112.json
├── nvdcve-2.0-113.json
├── nvdcve-2.0-114.json
├── nvdcve-2.0-115.json
├── nvdcve-2.0-116.json
├── nvdcve-2.0-117.json
├── nvdcve-2.0-118.json
├── nvdcve-2.0-119.json
├── nvdcve-2.0-120.json
└── nvdcve-2.0-121.json
1 directory, 122 files
VulnCheck’s Extended KEV
Here’s a curl
idiom for the extended KEV index backup. The result is a directory with a single uncompressed JSON that’s in an extended format of what’s in the CISA KEV JSON.s
# Grab the temporary AWS pre-signed URL for the NVDv2 index and then download the ZIP file.
curl \
--silent \
--output vckev.zip --url "$(
curl \
--silent \
--cookie "token=${VULNCHECK_API_KEY}" \
--header 'Accept: application/json' \
--url "https://api.vulncheck.com/v3/backup/vulncheck-kev" | jq -r '.data[].url'
)"
rm -rf ./vckev
# unzip it
unzip -q -o -d ./vckev vckev.zip
tree ./vckev
./vckev
└── vulncheck_known_exploited_vulnerabilities.json
1 directory, 1 file
Retrieving Information On Individual CVEs
While there are other, searchable fields for each index, the primary use case for most of us is getting information on individual CVEs. The API calls are virtually identical, apart from the selected index.
NOTE: the examples pipe the output through jq
to make the API results easier to read.
NVDv2
curl \
--silent \
--cookie "token=${VULNCHECK_API_KEY}" \
--header 'Accept: application/json' \
--url "https://api.vulncheck.com/v3/index/nist-nvd2?cve=CVE-2024-23334" | jq
{
"_benchmark": 0.056277,
"_meta": {
"timestamp": "2024-03-23T08:47:17.940032202Z",
"index": "nist-nvd2",
"limit": 100,
"total_documents": 1,
"sort": "_id",
"parameters": [
{
"name": "cve",
"format": "CVE-YYYY-N{4-7}"
},
{
"name": "alias"
},
{
"name": "iava",
"format": "[0-9]{4}[A-Z-0-9]+"
},
{
"name": "threat_actor"
},
{
"name": "mitre_id"
},
{
"name": "misp_id"
},
{
"name": "ransomware"
},
{
"name": "botnet"
},
{
"name": "published"
},
{
"name": "lastModStartDate",
"format": "YYYY-MM-DD"
},
{
"name": "lastModEndDate",
"format": "YYYY-MM-DD"
}
],
"order": "desc",
"page": 1,
"total_pages": 1,
"max_pages": 6,
"first_item": 1,
"last_item": 1
},
"data": [
{
"id": "CVE-2024-23334",
"sourceIdentifier": "security-advisories@github.com",
"vulnStatus": "Modified",
"published": "2024-01-29T23:15:08.563",
"lastModified": "2024-02-09T03:15:09.603",
"descriptions": [
{
"lang": "en",
"value": "aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. When using aiohttp as a web server and configuring static routes, it is necessary to specify the root path for static files. Additionally, the option 'follow_symlinks' can be used to determine whether to follow symbolic links outside the static root directory. When 'follow_symlinks' is set to True, there is no validation to check if reading a file is within the root directory. This can lead to directory traversal vulnerabilities, resulting in unauthorized access to arbitrary files on the system, even when symlinks are not present. Disabling follow_symlinks and using a reverse proxy are encouraged mitigations. Version 3.9.2 fixes this issue."
},
{
"lang": "es",
"value": "aiohttp es un framework cliente/servidor HTTP asíncrono para asyncio y Python. Cuando se utiliza aiohttp como servidor web y se configuran rutas estáticas, es necesario especificar la ruta raíz para los archivos estáticos. Además, la opción 'follow_symlinks' se puede utilizar para determinar si se deben seguir enlaces simbólicos fuera del directorio raíz estático. Cuando 'follow_symlinks' se establece en Verdadero, no hay validación para verificar si la lectura de un archivo está dentro del directorio raíz. Esto puede generar vulnerabilidades de directory traversal, lo que resulta en acceso no autorizado a archivos arbitrarios en el sistema, incluso cuando no hay enlaces simbólicos presentes. Se recomiendan como mitigaciones deshabilitar follow_symlinks y usar un proxy inverso. La versión 3.9.2 soluciona este problema."
}
],
"references": [
{
"url": "https://github.com/aio-libs/aiohttp/commit/1c335944d6a8b1298baf179b7c0b3069f10c514b",
"source": "security-advisories@github.com",
"tags": [
"Patch"
]
},
{
"url": "https://github.com/aio-libs/aiohttp/pull/8079",
"source": "security-advisories@github.com",
"tags": [
"Patch"
]
},
{
"url": "https://github.com/aio-libs/aiohttp/security/advisories/GHSA-5h86-8mv2-jq9f",
"source": "security-advisories@github.com",
"tags": [
"Exploit",
"Mitigation",
"Vendor Advisory"
]
},
{
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ICUOCFGTB25WUT336BZ4UNYLSZOUVKBD/",
"source": "security-advisories@github.com"
},
{
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XXWVZIVAYWEBHNRIILZVB3R3SDQNNAA7/",
"source": "security-advisories@github.com",
"tags": [
"Mailing List"
]
}
],
"metrics": {
"cvssMetricV31": [
{
"source": "nvd@nist.gov",
"type": "Primary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"attackVector": "NETWORK",
"attackComplexity": "LOW",
"privilegesRequired": "NONE",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "HIGH",
"integrityImpact": "NONE",
"availabilityImpact": "NONE",
"baseScore": 7.5,
"baseSeverity": "HIGH"
},
"exploitabilityScore": 3.9,
"impactScore": 3.6
},
{
"source": "security-advisories@github.com",
"type": "Secondary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
"attackVector": "NETWORK",
"attackComplexity": "HIGH",
"privilegesRequired": "NONE",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "HIGH",
"integrityImpact": "NONE",
"availabilityImpact": "NONE",
"baseScore": 5.9,
"baseSeverity": "MEDIUM"
},
"exploitabilityScore": 2.2,
"impactScore": 3.6
}
]
},
"weaknesses": [
{
"source": "security-advisories@github.com",
"type": "Primary",
"description": [
{
"lang": "en",
"value": "CWE-22"
}
]
}
],
"configurations": [
{
"nodes": [
{
"operator": "OR",
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:a:aiohttp:aiohttp:*:*:*:*:*:*:*:*",
"versionStartIncluding": "1.0.5",
"versionEndExcluding": "3.9.2",
"matchCriteriaId": "CC18B2A9-9D80-4A6E-94E7-8FC010D8FC70"
}
]
}
]
},
{
"nodes": [
{
"operator": "OR",
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:o:fedoraproject:fedora:39:*:*:*:*:*:*:*",
"matchCriteriaId": "B8EDB836-4E6A-4B71-B9B2-AA3E03E0F646"
}
]
}
]
}
],
"_timestamp": "2024-02-09T05:33:33.170054Z"
}
]
}
VulnCheck’s Extended KEV
curl \
--silent \
--cookie "token=${VULNCHECK_API_KEY}" \
--header 'Accept: application/json' \
--url "https://api.vulncheck.com/v3/index/vulncheck-kev?cve=CVE-2024-23334" | jq
{
"_benchmark": 0.328855,
"_meta": {
"timestamp": "2024-03-23T08:47:41.025967418Z",
"index": "vulncheck-kev",
"limit": 100,
"total_documents": 1,
"sort": "_id",
"parameters": [
{
"name": "cve",
"format": "CVE-YYYY-N{4-7}"
},
{
"name": "alias"
},
{
"name": "iava",
"format": "[0-9]{4}[A-Z-0-9]+"
},
{
"name": "threat_actor"
},
{
"name": "mitre_id"
},
{
"name": "misp_id"
},
{
"name": "ransomware"
},
{
"name": "botnet"
},
{
"name": "published"
},
{
"name": "lastModStartDate",
"format": "YYYY-MM-DD"
},
{
"name": "lastModEndDate",
"format": "YYYY-MM-DD"
},
{
"name": "pubStartDate",
"format": "YYYY-MM-DD"
},
{
"name": "pubEndDate",
"format": "YYYY-MM-DD"
}
],
"order": "desc",
"page": 1,
"total_pages": 1,
"max_pages": 6,
"first_item": 1,
"last_item": 1
},
"data": [
{
"vendorProject": "aiohttp",
"product": "aiohttp",
"shortDescription": "aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. When using aiohttp as a web server and configuring static routes, it is necessary to specify the root path for static files. Additionally, the option 'follow_symlinks' can be used to determine whether to follow symbolic links outside the static root directory. When 'follow_symlinks' is set to True, there is no validation to check if reading a file is within the root directory. This can lead to directory traversal vulnerabilities, resulting in unauthorized access to arbitrary files on the system, even when symlinks are not present. Disabling follow_symlinks and using a reverse proxy are encouraged mitigations. Version 3.9.2 fixes this issue.",
"vulnerabilityName": "aiohttp aiohttp Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')",
"required_action": "Apply remediations or mitigations per vendor instructions or discontinue use of the product if remediation or mitigations are unavailable.",
"knownRansomwareCampaignUse": "Known",
"cve": [
"CVE-2024-23334"
],
"vulncheck_xdb": [
{
"xdb_id": "231b48941355",
"xdb_url": "https://vulncheck.com/xdb/231b48941355",
"date_added": "2024-02-28T22:30:21Z",
"exploit_type": "infoleak",
"clone_ssh_url": "git@github.com:ox1111/CVE-2024-23334.git"
},
{
"xdb_id": "f1d001911304",
"xdb_url": "https://vulncheck.com/xdb/f1d001911304",
"date_added": "2024-03-19T16:28:56Z",
"exploit_type": "infoleak",
"clone_ssh_url": "git@github.com:jhonnybonny/CVE-2024-23334.git"
}
],
"vulncheck_reported_exploitation": [
{
"url": "https://cyble.com/blog/cgsi-probes-shadowsyndicate-groups-possible-exploitation-of-aiohttp-vulnerability-cve-2024-23334/",
"date_added": "2024-03-15T00:00:00Z"
}
],
"date_added": "2024-03-15T00:00:00Z",
"_timestamp": "2024-03-23T08:27:47.861266Z"
}
]
}
vccve
There’s a project on Codeberg that has code and binaries for macOS, Linux, and Windows for a small CLI that gets you combined extended KEV and NVDv2 information all in one call.
The project README has examples and installation instructions.
When Checks and Balances Fail: The State’s Role in Preserving Constitutional Order
Today, my Senator — Susan Collins — failed in her oath and duty to uphold the Constitution. She voted for the appointment of a traitor to head national intelligence, and is supporting someone for director of the Office of Management and Budget (OMB) who openly wants to dismantle the foundations of American government. She has done nothing to oppose the Administrative coup we’ve been witnessing since POTUS 47 took office. She is now, fully, a willing collaborator. The Executive branch is now nigh irreparably and wholly corrupted, and the Congress is — effectively — on a leash wielded by the POTUS.
The American system of government was designed with multiple layers of protection against the concentration and abuse of power. While we typically focus on federal checks and balances, states play a paramount role as independent sovereigns in our federal system, particularly when federal safeguards falter. Understanding these state powers is essential for maintaining constitutional governance.
The architects of American federalism deliberately created a system where states retain significant independent authority. This includes control over their law enforcement agencies, National Guard units, and the ability to refuse state resources for federal actions. Perhaps most importantly, states maintain the power to prosecute federal officials who act outside their legal authority and violate state laws. These powers weren’t accidents of history — they were deliberately preserved to prevent federal overreach.
Individual states become even more effective when they work together. Through formal interstate compacts and informal coordination, states can create powerful counterweights to federal overreach. This might involve sharing intelligence about illegal federal activities, coordinating legal responses, or pooling resources to resist unconstitutional actions. When multiple states stand together, their collective influence often exceeds the sum of their individual powers.
States control critical infrastructure and resources that federal authorities rely upon to function effectively. This gives states significant practical leverage through their ability to withhold cooperation on federal programs or impose economic consequences on entities that support illegal federal actions. While these powers should be used judiciously, they provide states with concrete tools to resist federal overreach.
Ultimately, the effectiveness of state resistance to federal overreach depends on democratic legitimacy and public support. State officials must be willing to uphold their constitutional oaths, local law enforcement must maintain order under state authority, and citizens must engage in civil resistance to support legitimate government. This democratic foundation is what transforms state powers from theoretical authorities into practical tools for preserving constitutional order.
It’s important to note that state resistance powers come with significant responsibilities. States must exercise these authorities carefully and only in response to genuine constitutional violations, not mere policy disagreements. The goal is to preserve constitutional order, not to create chaos or unnecessarily disrupt legitimate federal operations.
The distributed nature of American governance remains one of our strongest protections against tyranny. While a corrupt federal official might attempt to misuse power, success would require complicity from state and local institutions across the country. By understanding and preserving state powers to resist federal overreach, we maintain essential safeguards for constitutional governance.
The system of checks and balances becomes most critical precisely when it appears to be failing at the federal level. In these moments, state powers of resistance — exercised responsibly and with democratic support — provide crucial backup systems for preserving constitutional order. Understanding these powers helps ensure they remain available when needed most.
Unfortunately, the “Trump 25” states form a solid base of support across four geographic regions:
Several states are taking concrete actions to support federal initiatives:
Republican-led states are advancing legislation to:
This is just the beginning of their willing capitulation to a corrupt regime. It will only get worse.
I call on Maine’s Governor, Janet Mills, to work with the remaining states to do whatever it takes to uphold democratic principles and the rule of law. Without such a coalition, we will most certainly lose our Republic.