Skip to content

pgdn-oss/pgdn-cve

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

PGDN CVE Library

A simple Python library for downloading and managing CVE (Common Vulnerabilities and Exposures) data from the NVD (National Vulnerability Database) API.

Features

  • CVE Download: Fetch recent CVEs from NVD API
  • CVE Search: Search CVEs by keyword
  • Specific CVE Lookup: Download individual CVEs by ID
  • JSON Output: Clean JSON format for all operations
  • File Export: Save CVE data to JSON files
  • CLI Interface: Command-line tool for easy access

Installation

From PyPI (Recommended)

pip install pgdn-cve

From Source

# Clone the repository
git clone https://github.com/pgdn-network/pgdn-cve.git
cd pgdn-cve

# Install in development mode
pip install -e .

Development Installation

# Clone the repository
git clone https://github.com/pgdn-network/pgdn-cve.git
cd pgdn-cve

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install with development dependencies
pip install -e ".[dev]"

Building from Source

# Install build tools
pip install build

# Build the package
python -m build

# Install the built package
pip install dist/pgdn_cve-*.whl

Verification

After installation, verify the package works:

# Test library import
python -c "import pgdn_cve; print('Installation successful!')"

# Test CLI
pgdn-cve --help

Using as a Library

The PGDN CVE Library can be used as a Python package in your applications:

Basic Import

from pgdn_cve import CVEDownloader, download_cves, search_cves, iter_cves

Available Functions

  • download_cves(days_back=7, max_results=1000, timeout=30): Download recent CVEs
  • search_cves(keyword, max_results=100, timeout=30): Search CVEs by keyword
  • CVEDownloader: Class for more advanced usage
  • iter_cves(start_date=None, end_date=None, batch_size=1000): Efficiently iterate over all CVEs in batches (for incremental sync)

Simple Examples

import json
from pgdn_cve import download_cves, search_cves

# Download recent CVEs
recent_cves = download_cves(days_back=7, max_results=50)
print(f"Downloaded {len(recent_cves['cves'])} CVEs")

# Search for specific vulnerabilities
log4j_cves = search_cves("log4j", max_results=20)
print(f"Found {len(log4j_cves['cves'])} Log4j CVEs")

# Access individual CVE data
for cve in recent_cves['cves']:
    print(f"{cve['cve_id']}: {cve['severity']} - {cve['description'][:100]}...")

Incremental Batch Fetching Example (Efficient Sync)

If you want to fetch only new CVEs since your last pull, use the iter_cves function. This is ideal for production sync jobs:

from pgdn_cve import iter_cves

# Load this from your database or a state file
# You can use "YYYY-MM-DD", "YYYY-MM-DDTHH:MM:SS", or "YYYY-MM-DDTHH:MM:SS.000Z" format.
last_pull = load_last_pull_timestamp()  # e.g., "2024-06-28T00:00:00"

for batch in iter_cves(start_date=last_pull, batch_size=1000):
    # Process or save this batch
    save_to_db(batch)
    # Update last_pull to the latest published_date in this batch
    last_pull = max(
        (cve['published_date'] for cve in batch if cve.get('published_date')),
        default=last_pull
    )
    save_last_pull_timestamp(last_pull)

Date Format Notes:

  • You may pass start_date and end_date as YYYY-MM-DD, YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS.000Z.
  • The library will automatically convert your date to the correct NVD API format (YYYY-MM-DDTHH:MM:SS.000Z).
  • If you pass an end_date in the future, it will be capped at the current UTC time to avoid NVD API errors.

Advanced Usage with CVEDownloader Class

from pgdn_cve import CVEDownloader

# Using context manager (recommended)
with CVEDownloader() as downloader:
    # Download specific CVE
    cve_data = downloader.download_cve_by_id("CVE-2021-44228")
    print(f"CVE: {cve_data['cve_id']}")
    print(f"Severity: {cve_data['severity']}")
    
    # Download and save to file
    cves = downloader.download_recent_cves(days_back=30)
    result = downloader.save_cves_to_file(cves, "recent_cves.json")
    print(f"Saved {result['total_cves']} CVEs to file")

# Manual instantiation
downloader = CVEDownloader()
try:
    cves = downloader.download_recent_cves(days_back=7)
    print(f"Downloaded {len(cves['cves'])} CVEs")
finally:
    downloader.close()

Integration Examples

Flask Web Application

from flask import Flask, jsonify, request
from pgdn_cve import search_cves, download_cves

app = Flask(__name__)

@app.route('/api/cves/recent')
def get_recent_cves():
    days = request.args.get('days', 7, type=int)
    limit = request.args.get('limit', 100, type=int)
    
    try:
        result = download_cves(days_back=days, max_results=limit)
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/cves/search')
def search_cve():
    keyword = request.args.get('keyword')
    if not keyword:
        return jsonify({'error': 'Keyword required'}), 400
    
    try:
        result = search_cves(keyword)
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True)

Django Management Command

# management/commands/update_cves.py
from django.core.management.base import BaseCommand
from pgdn_cve import download_cves
from myapp.models import CVE

class Command(BaseCommand):
    help = 'Update CVE database from NVD'

    def add_arguments(self, parser):
        parser.add_argument('--days', type=int, default=7)
        parser.add_argument('--limit', type=int, default=1000)

    def handle(self, *args, **options):
        try:
            result = download_cves(
                days_back=options['days'],
                max_results=options['limit']
            )
            
            for cve_data in result['cves']:
                CVE.objects.update_or_create(
                    cve_id=cve_data['cve_id'],
                    defaults={
                        'description': cve_data['description'],
                        'severity': cve_data['severity'],
                        'cvss_score': cve_data['cvss_score'],
                    }
                )
            
            self.stdout.write(
                self.style.SUCCESS(f"Updated {len(result['cves'])} CVEs")
            )
        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f"Error updating CVEs: {e}")
            )

Quick Start

Library Usage

from pgdn_cve import CVEDownloader, download_cves, search_cves

# Download recent CVEs (last 7 days)
recent_cves = download_cves(days_back=7, max_results=100)
print(f"Downloaded {len(recent_cves)} CVEs")

# Search CVEs by keyword
log4j_cves = search_cves("log4j", max_results=50)
print(f"Found {len(log4j_cves)} Log4j CVEs")

# Using the CVEDownloader class directly
with CVEDownloader() as downloader:
    # Download specific CVE
    cve_data = downloader.download_cve_by_id("CVE-2021-44228")
    print(f"CVE: {cve_data['cve_id']}")
    print(f"Severity: {cve_data['severity']}")
    
    # Download and save to file
    cves = downloader.download_recent_cves(days_back=30)
    result = downloader.save_cves_to_file(cves, "recent_cves.json")
    print(f"Saved {result['total_cves']} CVEs to file")

CLI Usage

# Download recent CVEs (last 7 days)
pgdn-cve download

# Download CVEs from last 30 days
pgdn-cve download --days 30

# Download specific CVE
pgdn-cve download --cve-id CVE-2021-44228

# Search CVEs by keyword
pgdn-cve search --keyword "log4j"

# Save results to file
pgdn-cve download --days 7 --output recent_cves.json

# Search and save results
pgdn-cve search --keyword "apache" --limit 50 --output apache_cves.json

Output Format

All functions return CVE data in a standardized JSON format:

Single CVE Structure

{
  "cve_id": "CVE-2021-44228",
  "published_date": "2021-12-10T10:15:09.817Z",
  "last_modified": "2023-11-07T04:15:31.613Z",
  "source": "NVD",
  "description": "Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI features...",
  "severity": "CRITICAL",
  "cvss_score": 10.0,
  "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
  "references": [
    "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q",
    "https://www.apache.org/security/advisory.html"
  ],
  "download_timestamp": "2024-01-15T10:30:45.123456"
}

Download Response Structure

{
  "status": "success",
  "total_cves": 150,
  "days_back": 7,
  "cves": [
    {
      "cve_id": "CVE-2024-0001",
      "description": "...",
      "severity": "HIGH",
      ...
    }
  ]
}

Search Response Structure

{
  "status": "success",
  "keyword": "log4j",
  "total_cves": 25,
  "cves": [
    {
      "cve_id": "CVE-2021-44228",
      "description": "...",
      "severity": "CRITICAL",
      ...
    }
  ]
}

Command Line Interface

Download Command

pgdn-cve download [options]

Options:
  --days DAYS       Days back to fetch CVEs (default: 7)
  --limit LIMIT     Maximum number of CVEs (default: 1000)
  --cve-id CVE_ID   Download specific CVE by ID
  --output FILE     Save results to JSON file
  --timeout SEC     Request timeout in seconds (default: 30)

Search Command

pgdn-cve search --keyword KEYWORD [options]

Options:
  --keyword KEYWORD  Keyword to search for (required)
  --limit LIMIT      Maximum number of results (default: 100)
  --output FILE      Save results to JSON file
  --timeout SEC      Request timeout in seconds (default: 30)

Examples

Download Examples

# Download CVEs from last week
pgdn-cve download --days 7

# Download specific CVE with full details
pgdn-cve download --cve-id CVE-2021-44228

# Download recent CVEs and save to file
pgdn-cve download --days 30 --limit 500 --output monthly_cves.json

Search Examples

# Search for Log4j vulnerabilities
pgdn-cve search --keyword "log4j"

# Search for Apache vulnerabilities
pgdn-cve search --keyword "apache" --limit 100

# Search and save results
pgdn-cve search --keyword "nginx" --output nginx_cves.json

API Rate Limiting

The NVD API has rate limits. This library:

  • Respects API rate limits with appropriate delays
  • Uses reasonable default timeouts (30 seconds)
  • Handles API errors gracefully
  • Returns error information in JSON format

Error Handling

All functions return JSON responses with error information:

{
  "status": "error",
  "error": "Download failed",
  "details": "Connection timeout after 30 seconds"
}

Development

Setup Development Environment

git clone https://github.com/pgdn-network/pgdn-cve.git
cd pgdn-cve
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -e ".[dev]"

Run Tests

pytest

Code Formatting

black src/ tests/
isort src/ tests/
flake8 src/ tests/

Package Distribution

Building for Distribution

# Install build tools
pip install build twine

# Build source and wheel distributions
python -m build

# Check the built package
twine check dist/*

Publishing to PyPI

# Upload to Test PyPI first (recommended)
twine upload --repository testpypi dist/*

# Upload to PyPI
twine upload dist/*

Local Installation Testing

# Install from built wheel
pip install dist/pgdn_cve-*.whl

# Test the installation
python -c "import pgdn_cve; print('Success!')"
pgdn-cve --help

Dependencies

  • httpx: HTTP client for API requests
  • Python 3.8+: Minimum Python version

Data Source

This library fetches data from the official NVD API:

  • API Version: 2.0
  • Data Source: NIST National Vulnerability Database
  • Update Frequency: Real-time from NVD
  • Data Format: JSON

License

MIT License - see LICENSE file for details.

Troubleshooting

Common Installation Issues

Permission Errors

If you encounter permission errors during installation:

# Use --user flag for user installation
pip install --user pgdn-cve

# Or use a virtual environment (recommended)
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install pgdn-cve

Import Errors

If you get import errors after installation:

# Verify installation
pip list | grep pgdn-cve

# Check Python path
python -c "import sys; print(sys.path)"

# Reinstall if needed
pip uninstall pgdn-cve
pip install pgdn-cve

CLI Command Not Found

If the pgdn-cve command is not found:

# Check if entry point is installed
pip show pgdn-cve

# Try running with python -m
python -m pgdn_cve.cli --help

# Reinstall with --force-reinstall
pip install --force-reinstall pgdn-cve

Build Errors

If you encounter build errors:

# Update build tools
pip install --upgrade build setuptools wheel

# Clean and rebuild
make clean
make build

API Rate Limiting

If you encounter API rate limiting errors:

  • Reduce the number of concurrent requests
  • Increase delays between requests
  • Use smaller max_results values
  • Consider implementing caching for repeated queries

Network Issues

If you have network connectivity issues:

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Support

Usage Example: Fetching CVEs by Date Range (NVD API Style)

You can fetch CVEs in a date range using the same style as the NVD API docs:

from pgdn_cve import iter_cves
from pprint import pprint

# Always provide both start_date and end_date in YYYY-MM-DDTHH:MM:SS.000Z format
start_date = "2021-08-04T00:00:00.000Z"
end_date = "2021-10-23T00:00:00.000Z"

for batch in iter_cves(start_date=start_date, end_date=end_date, batch_size=1):
    if not batch:
        print("No CVEs found in this range.")
    else:
        pprint(batch)
  • If there are no CVEs in the range, the iterator yields an empty list (404 from NVD API is handled as 'no results').
  • Dates must be in the format YYYY-MM-DDTHH:MM:SS.000Z (or will be auto-formatted).
  • Both start_date and end_date are required for date-based queries.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published

Contributors 2

  •  
  •