# How SkillSpector Handles Offline or Air-Gapped Environments for Vulnerability Lookups

> SkillSpector ensures continuous security scanning in offline or air-gapped environments by falling back to a built-in static database for vulnerability lookups. Keep your systems secure.

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

---

**SkillSpector automatically falls back to a built-in static database of high-severity vulnerabilities when the OSV.dev API is unreachable, ensuring continuous security scanning in air-gapped or offline environments.**

When scanning AI skills for supply chain risks, NVIDIA's SkillSpector operates a two-stage vulnerability detection system under rule **SC4** (known vulnerable dependencies). If the scanner cannot reach the public internet—common in isolated CI runners or corporate networks—it seamlessly switches to an offline mode using a curated static list, guaranteeing that critical CVE detection continues without network access.

## How SkillSpector Detects Vulnerable Dependencies (SC4 Rule)

The SC4 analyzer 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) extracts dependency manifests—including [`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` (Python), and [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json) (npm)—and evaluates them against vulnerability data. According to the NVIDIA/SkillSpector source code, this process follows a strict priority: attempt live verification first, then fall back to static data if the network is unavailable.

### The Live OSV.dev Lookup (Online Path)

In online environments, SkillSpector queries the Open Source Vulnerabilities (OSV) database via the `query_batch(pkg_pairs, ecosystem)` function in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py). This function issues a single POST request to `https://api.osv.dev/v1/querybatch` and returns CVE data that is converted into `AnalyzerFinding` objects with severity ratings derived from the most severe CVE returned.

Results are cached in-memory for one hour (`_osv_cache`) to minimize repeated network traffic during batch operations.

### The Static Fallback Database (Offline Mode)

If the HTTP request fails or returns no coverage for specific packages, SkillSpector invokes `_sc4_from_fallback` to check against `_FALLBACK_VULNERABLE_PYPI` or `_FALLBACK_VULNERABLE_NPM`. These static lists contain a few dozen high-impact CVEs curated for offline use.

The fallback logic iterates over any dependency **not covered** by the OSV results and checks for name matches in the static database:

```python
def _sc4_from_fallback(...):
    """Emit SC4 findings from the static fallback list (offline mode)."""
    if max_safe is None:
        findings.append(
            AnalyzerFinding(
                rule_id="SC4",
                message=f"Known Vulnerable Dependency: {pkg_name} ({cve_info})",
                severity=Severity.HIGH,
                ...
            )
        )
    elif pkg_version and _version_lt(pkg_version, max_safe):
        findings.append(
            AnalyzerFinding(
                rule_id="SC4",
                message=(
                    f"Known Vulnerable Dependency: {pkg_name}=={pkg_version}"
                    f" (fix: >={max_safe}, {cve_info})"
                ),
                severity=Severity.HIGH,
                ...
            )
        )

```

Every finding generated through this path retains the `rule_id="SC4"` and a **high severity** rating, ensuring that security issues remain visible even without real-time CVE data.

### Integration Flow in the Analyzer Pipeline

The orchestration logic resides in `_analyze_dependencies` within [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py). After extracting packages, the workflow proceeds as follows:

1. Execute `_sc4_from_osv(...)` to perform the live lookup and identify which packages received OSV coverage.
2. Calculate `uncovered_packages` by filtering out any package names found in the OSV response.
3. Call `_sc4_from_fallback(uncovered_packages, fallback_db, ...)` to generate findings for remaining dependencies.
4. Extend the final findings list with both OSV and fallback results.

This approach ensures comprehensive coverage: online environments benefit from up-to-date vulnerability data, while air-gapped environments retain protection against known high-severity threats.

## Practical Code Examples

### Running a Standard Online Scan

```bash

# Normal execution queries OSV.dev for real-time vulnerability data

skillspector scan ./my-skill/

```

### Simulating an Air-Gapped Environment

```bash

# Block outbound HTTPS (e.g., via iptables or network namespaces)

# SkillSpector automatically uses the static fallback database

skillspector scan ./my-skill/

```

When operating offline, the output will reference the static fallback database rather than live CVE entries, but will still flag vulnerable dependencies with high severity.

### Using the Python API for Offline Analysis

```python
from skillspector import graph

# Force offline mode by running in an environment without internet access

result = graph.invoke({
    "input_path": "./my-skill/",
    "output_format": "json",
    "use_llm": False,  # Static-only analysis

})

for f in result["filtered_findings"]:
    if f["rule_id"] == "SC4":
        print(f"[{f['severity']}] {f['message']}")

```

This invocation produces SC4 findings based solely on the built-in static lists, requiring zero HTTP requests.

## Summary

- **Automatic failover**: SkillSpector attempts live OSV.dev lookups first, then seamlessly switches to static fallback lists when the network is unreachable.
- **High-severity coverage**: The offline database (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`) focuses on critical vulnerabilities, assigning `Severity.HIGH` to all findings.
- **Zero configuration**: Air-gapped detection requires no flags or manual settings; the scanner handles offline logic internally via `_sc4_from_fallback`.
- **Comprehensive support**: The analyzer covers both Python (PyPI) and JavaScript (npm) ecosystems through dedicated static lists.
- **Caching layer**: Online scans utilize `_osv_cache` with a one-hour TTL to optimize performance in connected environments.

## Frequently Asked Questions

### How does SkillSpector detect it is running in an offline environment?

SkillSpector does not explicitly check for network connectivity. Instead, it attempts the OSV.dev API call via `query_batch` in [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py). If the request fails or returns no data for specific packages, the `_analyze_dependencies` function automatically routes those uncovered packages to `_sc4_from_fallback`. This failure-driven approach ensures robust operation without requiring privileged network checks.

### What vulnerabilities are included in the static fallback database?

The static fallback lists contain a curated set of high-impact CVEs for PyPI and npm packages. While smaller than the live OSV database, these lists prioritize widespread vulnerabilities with severe security implications. Each finding generated from this database receives a `Severity.HIGH` rating regardless of the specific CVE details.

### Can I force SkillSpector to use only the offline database?

There is no explicit command-line flag to disable network access, but you can simulate an offline environment by blocking outbound HTTPS traffic to `api.osv.dev`. Alternatively, when using the Python API, you can mock or disable the `requests.post` call used by `query_batch` to trigger the fallback behavior automatically.

### Does the offline mode support all package ecosystems?

The static fallback currently focuses on **Python (PyPI)** and **npm (Node.js)** dependencies through the `_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM` lists. Support for additional ecosystems would require extending these static lists in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py).