# How SkillSpector's OSV.dev Integration Performs Live CVE Lookups

> Discover how SkillSpector uses OSV.dev integration for live CVE lookups, detecting vulnerabilities in Python and JavaScript dependencies without external databases.

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

---

**SkillSpector queries the OSV.dev batch API with built-in caching and graceful fallback mechanisms to deliver real-time CVE detection for Python and JavaScript dependencies without requiring external vulnerability databases.**

NVIDIA's SkillSpector performs live vulnerability lookups by integrating directly with the OSV.dev database. The implementation, found primarily in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py), enables the supply-chain analyzer to detect security vulnerabilities in PyPI and npm dependencies as part of its static analysis pipeline.

## How SkillSpector Performs Live CVE Lookups via OSV.dev

The integration follows a multi-stage pipeline that minimizes network traffic while maximizing detection accuracy. Each stage is implemented in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py) and orchestrated by the supply-chain analyzer.

### Building Package-Level Queries

For each dependency, SkillSpector constructs a JSON query containing the package name, optional version, and ecosystem identifier. The helper function `_build_query` (around lines 92-96) formats these into OSV-compliant structures:

- **PyPI packages**: Use the `ECOSYSTEM_PYPI` constant (`"PyPI"`)
- **npm packages**: Use the `ECOSYSTEM_NPM` constant (`"npm"`)

### In-Memory Caching Strategy

Before issuing HTTP requests, the client checks an in-process cache keyed by the tuple `(name, version, ecosystem)`. The implementation uses `_get_cached` and `_put_cache` (lines 56-80) with a fixed TTL of 3600 seconds (`_CACHE_TTL_SECS = 3600`). According to the SkillSpector source code, this prevents duplicate lookups for the same package within a single analysis run.

### Batch API Requests

All uncached queries are sent in a single POST request to `https://api.osv.dev/v1/querybatch` (defined as `_OSV_BATCH_URL` at lines 51-53). The batch approach reduces network overhead compared to individual requests for each dependency.

### Vulnerability Detail Fetching

For each vulnerability ID returned by the batch query, SkillSpector issues a GET request to `https://api.osv.dev/v1/vulns/<ID>`. The `_fetch_vuln_details` function (lines 86-100) limits processing to the first 10 IDs to avoid latency spikes. It parses the JSON into `VulnResult` objects containing:

- `vuln_id`: The OSV vulnerability identifier
- `summary`: Human-readable description
- `severity`: Calculated severity level
- `aliases`: Associated CVE numbers

## Severity Estimation Without External Dependencies

When OSV returns CVSS vectors but no explicit severity score, SkillSpector uses `_estimate_cvss_severity` (lines 101-146) to calculate a coarse severity band. As implemented in NVIDIA/SkillSpector, this internal estimation avoids pulling in heavy CVSS libraries while still categorizing vulnerabilities as **CRITICAL**, **HIGH**, **MEDIUM**, or **LOW**.

## Resilient Live CVE Lookup with Fallback Handling

SkillSpector ensures deterministic results even in air-gapped environments or during network failures.

### Pre-Flight Connectivity Tests

The `is_available()` function (lines 81-90) performs a lightweight POST with a dummy query to verify OSV.dev reachability before attempting full batch requests.

### Graceful Degradation

If the OSV request fails due to network errors, timeouts, or unavailability, `query_batch` returns empty result lists. The supply-chain analyzer then falls back to built-in static vulnerability databases (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`), ensuring the analysis completes without external dependencies.

## Integration with the Supply Chain Analyzer

The [`src/skillspector/nodes/analyzers/static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/static_patterns_supply_chain.py) module orchestrates the OSV integration:

1. **Dependency extraction**: Parses [`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)
2. **Batch invocation**: Calls `query_batch` with lists of `(name, version)` tuples and the appropriate ecosystem constant
3. **Finding generation**: Creates SC4 findings for each vulnerable package, including the most severe result and formatted advisory IDs via `_format_vuln_ids`
4. **Fallback processing**: Packages not covered by OSV or when OSV is unavailable are processed by `_sc4_from_fallback`

## Practical Example: Querying OSV.dev in SkillSpector

You can use the OSV client directly to check specific packages:

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

# Verify OSV.dev is reachable

if is_available():
    packages = [
        ("requests", "2.28.0"),   # PyPI

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

    ]
    
    # Query for PyPI vulnerabilities

    results = query_batch(packages, ECOSYSTEM_PYPI)
    
    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 unreachable – using static fallback")

```

In the supply-chain analyzer, this logic is invoked automatically during static analysis:

```python

# Inside static_patterns_supply_chain.py

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

# osv_results is List[List[VulnResult]] used to build findings

```

## Summary

- **Batch API Efficiency**: SkillSpector queries `https://api.osv.dev/v1/querybatch` with all uncached packages in a single request, minimizing network overhead.
- **Intelligent Caching**: An in-memory cache with a 3600-second TTL prevents redundant lookups for the same `(name, version, ecosystem)` tuple during analysis.
- **Resilient Design**: If OSV.dev is unreachable, the system falls back to static vulnerability lists (`_FALLBACK_VULNERABLE_PYPI`, `_FALLBACK_VULNERABLE_NPM`) to ensure consistent results.
- **Severity Estimation**: The `_estimate_cvss_severity` function calculates severity bands from CVSS vectors without external dependencies.
- **Integration Points**: The [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) module provides the core functionality, while [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) coordinates dependency extraction and finding generation.
- **Test Coverage**: Unit tests in [`tests/unit/test_osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/unit/test_osv_client.py) validate cache handling and error paths, while [`tests/unit/test_patterns_new.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/unit/test_patterns_new.py) tests the supply-chain integration.

## Frequently Asked Questions

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

SkillSpector implements multiple resilience mechanisms. The `is_available()` function performs a lightweight connectivity check before batch requests. If the OSV.dev API returns network errors or timeouts, `query_batch` returns empty lists, triggering the supply-chain analyzer to use built-in static vulnerability databases instead.

### What package ecosystems does SkillSpector's OSV.dev integration support?

The integration currently supports **PyPI** (Python) and **npm** (JavaScript) packages. These are identified by the `ECOSYSTEM_PYPI` and `ECOSYSTEM_NPM` constants in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py), corresponding to the OSV.dev ecosystem identifiers `"PyPI"` and `"npm"`.

### How does the caching mechanism work in SkillSpector's OSV client?

The client maintains an in-process cache keyed by the tuple `(package_name, version, ecosystem)`. Before sending HTTP requests, `_get_cached` checks for existing entries with a 3600-second TTL (`_CACHE_TTL_SECS`). After processing OSV responses, `_put_cache` stores the list of `VulnResult` objects for future lookups within the same analysis run.

### What is the severity estimation logic when CVSS vectors are present?

When OSV returns CVSS vectors without explicit severity scores, the `_estimate_cvss_severity` function (lines 101-146) parses the vector string to estimate a coarse severity band. This logic categorizes vulnerabilities as CRITICAL, HIGH, MEDIUM, or LOW without requiring external CVSS calculation libraries, keeping the dependency footprint minimal.