# How SkillSpector Implements OSV.dev Integration for CVE Lookups

> Learn how SkillSpector integrates with OSV.dev for efficient CVE lookups on your Python and JavaScript dependencies. Get real-time vulnerability data with caching for speed.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: how-to-guide
- Published: 2026-06-24

---

**SkillSpector queries the OSV.dev batch API to perform live CVE lookups on Python and JavaScript dependencies, caching results in-memory for one hour and falling back to a static vulnerability database when the service is unreachable.**

NVIDIA's SkillSpector leverages OSV.dev integration to provide real-time vulnerability detection for software supply chains. The implementation resides primarily in [`skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/skillspector/nodes/analyzers/osv_client.py) and enables automatic CVE identification for PyPI and npm packages without requiring local vulnerability databases.

## Query Generation and Batch API Requests

The OSV.dev client generates package-level queries using the private `_build_query` helper function. Each query contains the package name, optional version, and ecosystem identifier (`"PyPI"` or `"npm"`).

Uncached queries are batched into a single HTTPS POST request to `https://api.osv.dev/v1/querybatch`. The `_OSV_BATCH_URL` constant defines this endpoint, and the `query_batch` function orchestrates the request. The response returns a list of vulnerability IDs for each submitted package, which the client then processes individually.

## In-Memory Caching Strategy

To minimize network traffic and latency, the client implements an in-process cache with a one-hour TTL (`_CACHE_TTL_SECS = 3600`). Cache entries are keyed by the tuple `(name, version, ecosystem)`.

The `_get_cached` function checks for existing entries before initiating network requests, while `_put_cache` stores newly retrieved results. This design ensures that repeated analysis of the same dependency within a single process run does not trigger redundant API calls.

## Vulnerability Detail Retrieval and Severity Parsing

For each vulnerability ID returned by the batch query, the client fetches detailed records using `_fetch_vuln_details`. To prevent excessive latency, the implementation limits detail requests to the first ten IDs per package.

The function parses OSV.dev responses into `VulnResult` objects containing `vuln_id`, `summary`, `severity`, and `aliases` (including CVE numbers). When OSV reports only CVSS vectors without explicit severity ratings, the `_estimate_cvss_severity` function maps scores to coarse bands: **CRITICAL**, **HIGH**, **MEDIUM**, or **LOW**.

## Graceful Fallback and Offline Support

Before executing batch requests, the `is_available()` method performs a lightweight connectivity check by sending a dummy query to confirm reachability. If the OSV.dev service is unreachable due to network errors, timeouts, or air-gapped environments, `query_batch` returns empty result lists.

The supply-chain analyzer ([`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py)) detects these empty results and automatically falls back to built-in static vulnerability lists (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`). This guarantees deterministic vulnerability detection even without external connectivity.

## Integration with Supply-Chain Analysis

The [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) analyzer orchestrates the OSV.dev integration by extracting dependencies from [`requirements.txt`](https://github.com/NVIDIA/SkillSpector/blob/main/requirements.txt), [`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml), [`setup.py`](https://github.com/NVIDIA/SkillSpector/blob/main/setup.py), `Pipfile`, or [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json). It invokes `query_batch` with the appropriate ecosystem constant (`ECOSYSTEM_PYPI` or `ECOSYSTEM_NPM`).

For each package with identified vulnerabilities, the analyzer creates SC4 findings containing the most severe result and a human-readable advisory list via `_format_vuln_ids`. Packages not covered by OSV.dev or processed during offline mode route through `_sc4_from_fallback` for static pattern matching.

## Code Examples

The following example demonstrates direct usage of the OSV.dev client:

```python
from skillspector.nodes.analyzers.osv_client import (
    ECOSYSTEM_PYPI,
    ECOSYSTEM_NPM,
    query_batch,
    is_available,
)

# Check that the OSV.dev service is reachable

if is_available():
    # Build a list of (package, version) tuples

    packages = [
        ("requests", "2.28.0"),   # PyPI package

        ("lodash", "4.17.20"),    # npm package

    ]

    # Query the OSV.dev batch endpoint for PyPI packages

    results = query_batch(packages, ECOSYSTEM_PYPI)

    # Inspect the returned VulnResult objects

    for pkg, vulns in zip(packages, results):
        name, version = pkg
        if not vulns:
            print(f"{name} ({version}) – no known CVEs")
            continue

        print(f"{name} ({version}) – {len(vulns)} CVE(s) found:")
        for v in vulns:
            print(f"  • {v.vuln_id} – {v.summary[:80]} (severity={v.severity})")
else:
    print("OSV.dev endpoint not reachable – falling back to static data")

```

Within the supply-chain analyzer, the integration operates automatically:

```python

# Inside static_patterns_supply_chain.py

pkg_pairs = [(name, version) for name, version, _ in packages]
osv_results = query_batch(pkg_pairs, ecosystem)   # live OSV lookup

# Each osv_results entry is a list[VulnResult] used to build SC4 findings

```

## Summary

- **Batch API**: The client sends aggregated queries to `https://api.osv.dev/v1/querybatch` to minimize network overhead.
- **Caching**: In-memory caching with 3600-second TTL prevents redundant lookups for repeated dependencies.
- **Severity Estimation**: Custom CVSS parsing estimates severity bands without external libraries.
- **Offline Support**: Automatic fallback to static vulnerability databases ensures reliability in air-gapped environments.
- **Ecosystem Coverage**: Supports both PyPI and npm ecosystems via `ECOSYSTEM_PYPI` and `ECOSYSTEM_NPM` constants.

## Frequently Asked Questions

### How does SkillSpector handle network failures when querying OSV.dev?

The `is_available()` function performs a lightweight connectivity check before attempting batch requests. If the OSV.dev endpoint is unreachable, `query_batch` returns empty lists, triggering the supply-chain analyzer to fall back to static vulnerability databases defined in `_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`.

### What is the caching mechanism for OSV.dev queries in SkillSpector?

The OSV client maintains an in-process cache keyed by `(package_name, version, ecosystem)` with a one-hour TTL (`_CACHE_TTL_SECS = 3600`). The `_get_cached` and `_put_cache` helper functions manage cache read/write operations, ensuring that duplicate vulnerability lookups within the same process execution do not generate redundant API traffic.

### Which package ecosystems does SkillSpector support for OSV.dev CVE lookups?

SkillSpector supports **PyPI** and **npm** ecosystems through the `ECOSYSTEM_PYPI` and `ECOSYSTEM_NPM` constants. The supply-chain analyzer automatically extracts dependencies from Python-specific files ([`requirements.txt`](https://github.com/NVIDIA/SkillSpector/blob/main/requirements.txt), [`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml), [`setup.py`](https://github.com/NVIDIA/SkillSpector/blob/main/setup.py), `Pipfile`) and JavaScript [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json) manifests for vulnerability scanning.

### How does SkillSpector determine severity levels for OSV.dev vulnerabilities?

When OSV.dev returns CVSS vectors without explicit severity fields, the `_estimate_cvss_severity` function parses the vector to calculate a coarse severity band. This mechanism categorizes vulnerabilities as CRITICAL, HIGH, MEDIUM, or LOW without requiring external CVSS calculation libraries, keeping the dependency footprint minimal.