# How OSV.dev Live Vulnerability Lookup Handles Offline Fallbacks in NVIDIA SkillSpector

> Learn how SkillSpector's OSV.dev integration ensures continuous SC4 scanning via offline fallbacks to a static vulnerability database, even in air-gapped environments.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: internals
- Published: 2026-07-08

---

**SkillSpector implements a resilient two-tiered OSV.dev integration that automatically falls back to a curated static vulnerability database when the live API is unreachable, ensuring continuous SC4 supply-chain scanning even in air-gapped environments.**

NVIDIA SkillSpector detects supply-chain vulnerabilities through the **SC4** rule by querying the OSV.dev public API for real-time dependency data. When network connectivity to `api.osv.dev` is unavailable, the analyzer gracefully degrades to a hard-coded fallback list of known vulnerable packages, ensuring security scanning remains operational while clearly signaling degraded data quality to users.

## Live Query Architecture with httpx

The OSV.dev integration centers on the `query_batch` function in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py) (lines 62-99), which constructs batch requests to `_OSV_BATCH_URL` containing all package name/version pairs extracted from dependency files.

The implementation uses **httpx** for HTTP transport and maintains an in-memory TTL cache (`_cache`) to avoid redundant network calls for identical packages. A module-level flag `_last_query_ok` tracks API health: the function sets it to `True` on successful queries and clears it to `False` on any `httpx`-related exception (lines 46-53). Critically, `query_batch` never raises exceptions; it returns empty result lists on failure, allowing the analyzer to proceed immediately to fallback logic.

## Mapping OSV Results to Security Findings

After receiving live data, the `_sc4_from_osv` function (lines 661-680 in [`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)) processes the returned `VulnResult` objects. It iterates over vulnerabilities for each package, identifies the highest severity, and creates an `AnalyzerFinding` for each vulnerable dependency.

During this mapping, the function populates a `covered` set containing normalized package names for which OSV returned at least one vulnerability. This set becomes the critical input for determining which packages require fallback coverage.

## Offline Fallback Mechanisms

When the live OSV.dev query completes—whether successfully or not—SkillSpector executes fallback logic to maximize coverage.

### Static Vulnerability Database

For any packages not present in the `covered` set, the analyzer invokes `_sc4_from_fallback` (lines 886-904) in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py). This function references hard-coded static lists (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`) containing known high-risk packages for Python and JavaScript ecosystems. This ensures that even without network access, SkillSpector can flag critical vulnerabilities like compromised versions of popular libraries.

### Detecting Complete OSV Outages

The system distinguishes between partial coverage (some packages unknown to OSV) and complete API failure. When `uncovered_packages` exist but `osv_findings` is empty and `was_osv_reachable()` (lines 166-173 in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py)) returns `False`, the analyzer injects a low-severity "fallback active" finding. This explicitly warns users that the OSV.dev service was unreachable and only static fallback data—if any—was utilized for the scan.

## Complete Implementation Example

The following pattern demonstrates how SkillSpector orchestrates live queries, fallback application, and offline detection:

```python
from skillspector.nodes.analyzers.osv_client import query_batch, was_osv_reachable
from skillspector.nodes.analyzers.static_patterns_supply_chain import (
    _sc4_from_osv, _sc4_from_fallback, _FALLBACK_VULNERABLE_PYPI
)

# 1️⃣ Build list of packages from a requirements.txt file

packages = [("requests", "2.31.0", 12), ("unknown_pkg", None, 20)]

# 2️⃣ Perform live OSV.dev lookup

osv_findings, covered = _sc4_from_osv(packages, "PyPI", "requirements.txt", ["SC4"])

# osv_findings → AnalyzerFinding objects for vulnerabilities returned

# covered → set of normalized package names OSV answered for

# 3️⃣ Apply static fallback for packages not covered by OSV

uncovered = [p for p in packages if p[0].lower().replace("_", "-") not in covered]
fallback_findings = _sc4_from_fallback(
    uncovered,
    _FALLBACK_VULNERABLE_PYPI,
    "requirements.txt",
    ["SC4"]
)

# 4️⃣ Detect offline mode (e.g., air‑gapped CI)

if not was_osv_reachable():
    print("⚠️ OSV.dev unreachable – only static fallback data is available")

```

## Summary

- **Resilient architecture**: The `query_batch` function in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) uses a `_last_query_ok` flag to track API health without throwing exceptions, ensuring the analyzer always receives a list result.
- **Coverage tracking**: The `covered` set in `_sc4_from_osv` identifies which packages received live OSV data, enabling targeted fallback application.
- **Dual fallback strategy**: SkillSpector applies `_sc4_from_fallback` for partial coverage gaps and emits a warning finding when `was_osv_reachable()` indicates complete OSV.dev unavailability.
- **Air-gapped support**: Hard-coded static lists (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`) provide critical vulnerability detection in environments where `api.osv.dev` is blocked.

## Frequently Asked Questions

### How does SkillSpector detect when OSV.dev is unreachable?

The `was_osv_reachable()` function checks the module-level `_last_query_ok` flag set during the previous `query_batch` execution. If any `httpx` exception occurred during the batch request to `_OSV_BATCH_URL`, the flag becomes `False`, signaling that subsequent results derive from static fallback data only.

### What happens if only some packages are missing from OSV.dev?

When OSV returns data for some but not all packages (the `covered` set is incomplete), SkillSpector calls `_sc4_from_fallback` specifically for the uncovered packages. This partial fallback ensures maximum vulnerability coverage without duplicating alerts for packages already verified clean by the live API.

### Does the static fallback contain all known vulnerabilities?

No. The static fallback uses small hard-coded lists (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`) containing only high-profile vulnerable packages. When operating in offline mode, the analyzer emits a specific warning finding to inform users that the results may be incomplete compared to a live OSV.dev query.

### Will offline fallback trigger CI/CD pipeline failures?

The fallback findings are generated at the same severity levels as live OSV data (based on the static list contents), but when the OSV.dev API is completely unreachable, SkillSpector adds a low-severity informational finding to flag the degraded data quality. Pipeline behavior depends on your configured severity thresholds for the SC4 rule.