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

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 extracts dependency manifests—including requirements.txt, pyproject.toml, setup.py, Pipfile (Python), and 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. 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:

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. 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


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

skillspector scan ./my-skill/

Simulating an Air-Gapped Environment


# 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

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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →