# How SkillSpector Handles Offline Environments for OSV.dev: Resilient Vulnerability Scanning

> Discover how SkillSpector ensures continuous OSV.dev scanning in offline environments by catching network errors, returning empty lists, and using its static vulnerability database.

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

---

**SkillSpector gracefully handles unreachable OSV.dev services by catching network exceptions, returning empty lists, and falling back to a built-in static vulnerability database, ensuring continuous operation in air-gapped environments.**

NVIDIA's SkillSpector is designed to operate in secure, offline environments where external API access is restricted. When the OSV.dev vulnerability database cannot be reached, the tool implements a multi-layered resilience strategy centered in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py) that maintains scanning capabilities without network connectivity.

## Network Failure Protection in osv_client.py

The OSV client implements robust **exception handling** to survive complete network isolation. Within the `query_batch` function, all HTTP calls are wrapped in `try/except` blocks that specifically catch `httpx.HTTPError`, `httpx.TimeoutException`, and parsing errors including `ValueError` and `KeyError`.

When any exception occurs, the client logs a warning message and returns an empty list for every package in the batch rather than propagating the error:

```python
except (httpx.HTTPError, httpx.TimeoutException, ValueError, KeyError) as exc:
    logger.warning("OSV.dev API request failed, falling back to static data: %s", exc)
    return [[] for _ in packages]

```

This pattern ensures that upstream analyzers receive the expected list structure even when the OSV.dev API is completely unreachable, preventing pipeline crashes in offline environments.

## In-Memory Caching for Resilience

SkillSpector reduces network dependency through **time-based caching**. The OSV client stores successful query results for `_CACHE_TTL_SECS = 3600` (one hour). 

When operating in intermittent connectivity environments, this cache allows the scanner to reference recent vulnerability data without requiring fresh API calls. If the service becomes unreachable during a scan session, cached results for previously queried packages remain available for the duration of the TTL window.

## Graceful Degradation to Static Vulnerability Patterns

When live OSV.dev queries fail, SkillSpector automatically activates its **static vulnerability database**. The upstream analyzer [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) expects `query_batch` to always return a list (potentially empty). 

Upon receiving empty results from the offline client, the analyzer merges these with a curated static vulnerability list that ships with the repository. This embedded dataset contains high-impact CVEs for common packages, ensuring the scanner still produces actionable security findings even without live look-ups.

## Proactive Connectivity Checking

To avoid unnecessary network timeouts, SkillSpector provides the **`is_available()`** helper function in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py). This method issues a lightweight POST request to the OSV.batch endpoint before attempting full batch queries.

Applications can leverage this check to proactively determine connectivity status:

```python
from skillspector.nodes.analyzers.osv_client import query_batch, is_available

# Example list of dependencies (name, version)

deps = [("requests", "2.28.1"), ("flask", None)]

# Check whether the live OSV service can be reached

if is_available():
    results = query_batch(deps, ecosystem="PyPI")
else:
    # OSV.dev is unreachable → rely on static data (empty lists here)

    results = [[] for _ in deps]

for (name, _), vulns in zip(deps, results):
    if vulns:
        print(f"{name} has {len(vulns)} known vulnerabilities")
    else:
        print(f"{name} – no live data; using static fallback")

```

When `is_available()` returns `False` in air-gapped environments, the code path skips network attempts and immediately utilizes the static fallback mechanism.

## Summary

- **Exception handling**: The `query_batch` function in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) catches `httpx.HTTPError`, timeouts, and parsing errors, returning empty lists instead of crashing the pipeline.
- **Caching layer**: Successful queries are cached for 3600 seconds, providing a buffer against transient network failures.
- **Static fallback**: The [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) analyzer activates a built-in vulnerability database when OSV.dev cannot be reached.
- **Connectivity detection**: The `is_available()` function enables proactive detection of offline environments before attempting API calls.

## Frequently Asked Questions

### What happens when OSV.dev is completely unreachable in SkillSpector?

SkillSpector catches the network exception in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py), logs a warning, and returns empty lists for all packages. This triggers the supply chain analyzer to use its built-in static vulnerability database instead of live OSV data, allowing scans to complete without internet access.

### Does SkillSpector cache OSV.dev responses for offline use?

Yes. The client caches successful API responses for 3600 seconds (one hour) using the `_CACHE_TTL_SECS` constant defined in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py). If the service goes offline, recent query results remain available from memory for the duration of the cache window.

### Can SkillSpector detect if OSV.dev is available before attempting queries?

Yes. The `is_available()` function in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) performs a lightweight connectivity check to the OSV.batch endpoint. Applications can call this method to decide whether to attempt live queries or skip directly to static analysis, preventing unnecessary timeout delays in offline environments.

### What vulnerability data is available when running offline?

When OSV.dev cannot be reached, SkillSpector falls back to a static vulnerability list embedded in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py). This curated dataset contains high-impact CVEs for common packages, ensuring the scanner still produces security findings without internet access.