# Understanding SkillSpector's SC4 Supply Chain Security Scanning: Core Components Explained

> Explore SkillSpector's SC4 Supply Chain Security Scanning. Learn about its dual vulnerability detection: live OSV.dev API and static database for Python and npm.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: deep-dive
- Published: 2026-06-20

---

**SkillSpector's SC4 check implements a two-tiered vulnerability detection system that combines live OSV.dev API queries with a static fallback database to identify known vulnerable dependencies in Python and npm manifests.**

Supply chain security scanning in SkillSpector centers on the SC4 analysis rule, which detects known vulnerable dependencies within Python and JavaScript projects. According to the NVIDIA/SkillSpector source code, this check operates as a self-contained pipeline within the graph-based analysis framework. The implementation prioritizes reliability through a dual-layer approach that ensures vulnerability detection even in air-gapped or offline environments.

## The Two-Tiered Architecture of SC4

### Live OSV.dev Integration

The primary detection mechanism relies on the OSV client module located in [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py). This component exposes the `query_batch()` function, which communicates with the OSV.dev batch API to retrieve real-time vulnerability data for specified packages. The client implements intelligent caching with a one-hour TTL to minimize API calls and converts raw OSV responses into standardized `VulnResult` objects with normalized severity mappings.

### Static Fallback Database

When network connectivity is unavailable or the OSV endpoint returns errors, SC4 falls back to deterministic vulnerability tables defined 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). These tables, `_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`, store package names, maximum safe versions, CVE descriptions, and confidence scores. This ensures that critical security checks continue functioning in restricted network environments.

## Core Components of the SC4 Pipeline

### OSV Client Module

The [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) file handles API communication, result caching, and severity extraction. It maps OSV severity fields to the internal `Severity` enum and provides connectivity probes to validate network availability before attempting live queries.

### SC4 Orchestration Helpers

The `_sc4_from_osv()` and `_sc4_from_fallback()` functions in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) standardize vulnerability findings into `AnalyzerFinding` objects. These helpers compute worst-case severity scores and assign confidence ratings using `_SEVERITY_CONFIDENCE` while ensuring consistent output formatting regardless of the data source.

### Dependency File Driver

The `_analyze_dependencies()` function serves as the main entry point for SC4 analysis. It detects manifest file types (Python's [`requirements.txt`](https://github.com/NVIDIA/SkillSpector/blob/main/requirements.txt) or [`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml), npm's [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json)), extracts package names and versions using ecosystem-specific parsers, and coordinates between live OSV lookups and static fallback validation.

### Graph Node Entry Point

The `node()` function integrates SC4 into SkillSpector's analysis workflow by iterating over component files cached in `SkillspectorState`. It executes regex-based patterns (SC1-SC3) via `static_runner`, then invokes `_analyze_dependencies` for each dependency manifest, aggregating findings into the final result set.

## How the SC4 Components Interact

The supply chain security scanning pipeline follows a strict sequence to ensure comprehensive coverage:

1. **File Detection**: The `node()` function scans `state["components"]` for dependency manifests and retrieves source text from `state["file_cache"]`.

2. **Package Extraction**: `_analyze_dependencies()` parses manifests into tuples of `(name, version, line)` using ecosystem-specific extractors like `_extract_packages_from_requirements` for Python or `_extract_packages_from_package_json` for npm.

3. **Live Lookup**: `_sc4_from_osv()` calls `osv_client.query_batch()` with ecosystem identifiers (`ECOSYSTEM_PYPI` or `ECOSYSTEM_NPM`).

4. **Fallback Validation**: Packages with no OSV results are checked against `_FALLBACK_VULNERABLE_*` tables.

5. **Result Building**: Both paths generate `AnalyzerFinding` objects containing rule ID "SC4", CVE details, severity levels, and file locations.

## Practical Code Examples

### Querying OSV Directly

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

# Ask OSV.dev whether the package "requests" has known vulnerabilities

results = query_batch([("requests", None)], ECOSYSTEM_PYPI)

# results contains VulnResult objects with severity and summary

for vuln in results[0]:
    print(vuln.vuln_id, vuln.severity, vuln.summary)

```

### Running SC4 Analysis on Requirements

```python
from skillspector.nodes.analyzers.static_patterns_supply_chain import (
    _analyze_dependencies,
)

requirements_txt = """
flask==2.0.1
pyyaml==5.4
unknown_pkg==0.1
"""

findings = _analyze_dependencies(requirements_txt, "requirements.txt")
for f in findings:
    print(f.rule_id, f.message, f.severity.name)

```

### Integrating with the Analysis Graph

```python
from skillspector.state import SkillspectorState

# Minimal state containing one dependency file

state = SkillspectorState(
    components=["requirements.txt"],
    file_cache={"requirements.txt": "requests==2.31.0\n"},
)

# Execute the supply-chain node (SC1-SC6)

node = __import__(
    "skillspector.nodes.analyzers.static_patterns_supply_chain",
    fromlist=["node"]
).node
response = node(state)

for finding in response["findings"]:
    print(finding.rule_id, finding.message)

```

## Summary

- **SC4** implements a resilient two-tiered detection system combining live OSV.dev queries with offline vulnerability databases defined in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py).
- The architecture centers on four main components: the OSV client ([`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py)), static fallback tables, orchestration helpers (`_sc4_from_osv` and `_sc4_from_fallback`), and the graph node entry point (`node()`).
- Key implementation files include [`src/skillspector/nodes/analyzers/osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/osv_client.py) for API interaction and [`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) for SC4 logic.
- The system gracefully degrades from network-based lookups to static analysis when connectivity is unavailable, ensuring continuous supply chain security scanning.

## Frequently Asked Questions

### What file types does SC4 support for dependency scanning?

SC4 analyzes Python manifests including [`requirements.txt`](https://github.com/NVIDIA/SkillSpector/blob/main/requirements.txt) and [`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml), as well as npm's [`package.json`](https://github.com/NVIDIA/SkillSpector/blob/main/package.json) files. The `_analyze_dependencies()` function in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py) automatically detects the file type and applies the appropriate parser for extracting package names and versions.

### How does SC4 handle network outages or air-gapped environments?

When the OSV.dev API is unreachable, SC4 automatically falls back to static vulnerability tables (`_FALLBACK_VULNERABLE_PYPI` and `_FALLBACK_VULNERABLE_NPM`) defined in [`static_patterns_supply_chain.py`](https://github.com/NVIDIA/SkillSpector/blob/main/static_patterns_supply_chain.py). These tables contain known vulnerable packages and versions, ensuring continuous security scanning without external connectivity.

### What is the difference between `_sc4_from_osv` and `_sc4_from_fallback`?

`_sc4_from_osv()` processes live API results from OSV.dev, extracting CVE IDs and severity scores from the response. `_sc4_from_fallback()` checks packages against the static vulnerability lists when live queries fail or return no results. Both functions normalize findings into `AnalyzerFinding` objects with consistent severity mappings and confidence scores.

### How does the caching mechanism work in the OSV client?

The [`osv_client.py`](https://github.com/NVIDIA/SkillSpector/blob/main/osv_client.py) module implements a one-hour result cache for batch queries to minimize API calls and improve performance. This caching layer operates transparently, storing raw OSV responses and returning cached `VulnResult` objects for identical subsequent queries within the cache window.