# How the SC4 Module in SkillSpector Performs Live Vulnerability Lookups

> Discover how the SkillSpector SC4 module ensures live vulnerability lookups using the OSV.dev API, CVSS scoring, and offline fallbacks for secure environments.

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

---

**The SC4 module performs live vulnerability lookups by querying the OSV.dev batch API with cached, ecosystem-specific package metadata, then mapping CVSS scores to severity levels while maintaining an offline fallback for air-gapped environments.**

The SC4 (*Known Vulnerable Dependencies*) rule is a critical component of NVIDIA's SkillSpector supply-chain security analyzer. When scanning dependency manifests such as [`requirements.txt`](https://github.com/NVIDIA/SkillSpector/blob/main/requirements.txt), [`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml), or [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json), the module extracts package identifiers and delegates real-time vulnerability detection to a dedicated OSV client. This architecture ensures that SkillSpector can identify known CVEs in open-source dependencies without requiring local vulnerability databases.

## Overview of the SC4 Vulnerability Detection Pipeline

SC4 is implemented 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). The analyzer detects dependency files during graph traversal, parses package names and versions, and passes these tuples to the OSV client located at [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py).

The client encapsulates the entire live-lookup workflow, handling everything from request caching to severity estimation. If the OSV.dev API becomes unreachable, the analyzer transparently switches to static fallback lists defined as `_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM` in the supply-chain module.

## Step-by-Step Live Lookup Workflow

### In-Memory Caching Layer

Before issuing any network request, the OSV client checks an in-memory cache keyed by the tuple `(name, version, ecosystem)`. The `_get_cached` method validates entries against a **one-hour TTL** (`_CACHE_TTL_SECS`), while `_put_cache` stores results to minimize redundant API calls. This caching strategy significantly improves performance when scanning monorepos with repeated dependencies.

### Batch Query Construction and Submission

For each uncached package, the client constructs a JSON payload via `_build_query` compatible with the OSV batch API. The `query_batch` function then POSTs these queries to `https://api.osv.dev/v1/querybatch`, respecting the configurable `_REQUEST_TIMEOUT`. 

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

# Packages extracted from a requirements file

packages = [("pyyaml", "6.0"), ("requests", "2.31.0")]

# Perform the live OSV lookup

vuln_lists = query_batch(packages, ECOSYSTEM_PYPI)

for (name, version), vulns in zip(packages, vuln_lists):
    if vulns:
        print(f"{name}=={version} has {len(vulns)} vulnerability(ies):")
        for v in vulns:
            print(f"  - {v.vuln_id}: {v.summary} [{v.severity}]")
    else:
        print(f"{name}=={version} is clean")
        

# Detect whether the API was reachable

print("OSV reachable:", was_osv_reachable())

```

### Advisory Detail Retrieval

When the batch API reports vulnerabilities, the client extracts advisory IDs and fetches full details via the single-vulnerability endpoint (`_OSV_VULN_URL`). The implementation retrieves up to **10 advisories per call** to balance thoroughness with API rate limits. Results are cached immediately to prevent re-fetching during the same scan session.

### Severity Classification Logic

The client derives severity through a hierarchical fallback strategy:

1. **Primary**: `database_specific.severity` (GHSA data)
2. **Secondary**: `affected[].ecosystem_specific.severity`
3. **Tertiary**: Parsed CVSS vector via `_estimate_cvss_severity`, mapping metric counts to **CRITICAL**, **HIGH**, **MEDIUM**, or **LOW**
4. **Default**: **HIGH** when no severity data exists

This ensures that every vulnerability receives a consistent severity label regardless of the advisory source.

## Resilience with Offline Fallback Mode

If the batch request fails due to network errors, timeouts, or malformed responses, the OSV client sets `_last_query_ok` to `False` and returns empty lists for all packages. The SC4 analyzer detects this state and activates static fallback mode, comparing dependencies against curated lists of known vulnerable packages for PyPI and NPM.

```python

# Inside static_patterns_supply_chain.py (SC4 path)

def _sc4_from_osv(packages, ecosystem):
    """Run live OSV lookup and emit SC4 findings."""
    results = query_batch(packages, ecosystem)
    findings = []
    for (name, version), vulns in zip(packages, results):
        if vulns:
            # Collapse multiple advisories into a single finding

            highest = max(vulns, key=lambda v: v.severity)
            findings.append(
                AnalyzerFinding(
                    rule_id="SC4",
                    location=Location(...),
                    severity=Severity[highest.severity],
                    message=f"{name}{'=='+version if version else ''}: {len(vulns)} CVE(s)",
                )
            )
    return findings

```

Finally, the analyzer converts each `VulnResult` into a `Finding` object with the `SC4` rule identifier, attaches location metadata, and returns these findings to the main graph traversal pipeline.

## Summary

- **SC4** performs live vulnerability lookups via the OSV.dev batch API in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py).
- **Caching** reduces API load with a one-hour TTL on `(package, version, ecosystem)` tuples.
- **Severity estimation** prefers GHSA data, falls back to CVSS parsing, and defaults to HIGH when unavailable.
- **Fallback mode** activates automatically when `_last_query_ok` is False, using static lists of known vulnerable packages.
- The implementation handles **batch queries**, **detail retrieval**, and **connectivity checks** to maintain performance in both online and offline environments.

## Frequently Asked Questions

### What does SC4 stand for in SkillSpector?

SC4 stands for **Known Vulnerable Dependencies**, the fourth supply-chain security rule in the SkillSpector analyzer suite. It specifically targets CVEs in third-party dependencies extracted from manifest files.

### How does the OSV client handle network failures?

The client sets an internal `_last_query_ok` flag to `False` when requests timeout or return errors, emits a warning log, and returns empty vulnerability lists. The SC4 analyzer then automatically switches to static fallback lists defined in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) to ensure scanning continues uninterrupted.

### What vulnerability databases does SC4 query?

SC4 queries the **OSV.dev** (Open Source Vulnerabilities) database via the public API at `api.osv.dev`. This aggregates advisories from GitHub Security Advisory (GHSA), PyPI Advisory Database, NPM Security Advisories, and other ecosystem-specific sources.

### How long are vulnerability lookups cached?

Results are cached in memory for **one hour** (`_CACHE_TTL_SECS = 3600`). The cache key combines the package name, version string, and ecosystem identifier to prevent collisions across different package managers.