# How to Interpret SARIF Output Format from NVIDIA SkillSpector for Security Tool Integration

> Learn to interpret SARIF output from NVIDIA SkillSpector for seamless security tool integration. Leverage structured JSON for CI pipelines and vulnerability dashboards.

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

---

**NVIDIA SkillSpector emits static analysis results in SARIF 2.1.0 format, enabling direct integration with CI pipelines, vulnerability dashboards, and security orchestration platforms by consuming the structured JSON output defined in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py).**

SkillSpector is an open-source static analysis tool from NVIDIA that generates security findings using the standardized Static Analysis Results Interchange Format (SARIF). To integrate these results with your security tooling, you must understand how SkillSpector structures its SARIF output and how to parse the specific fields defined in its Pydantic models. This guide walks through the exact schema definitions, validation methods, and integration patterns found in the SkillSpector repository.

## Understanding the SARIF 2.1.0 Log Structure in SkillSpector

### The Top-Level SarifLog Object

The root of every SkillSpector output is a `SarifLog` object defined in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py). This object contains three critical fields: `version` (fixed to `"2.1.0"`), `schema_` (containing the URI `"https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json"`), and `runs` (a list of `SarifRun` objects).

A model validator at lines 15-19 ensures that the `runs` array is never empty, guaranteeing that every log contains at least one analysis run.

### The SarifRun Container

Each run encapsulates the tool execution metadata and findings. According to the `SarifRun` definition at lines 99-104, each run includes a `tool` field (describing the analyzer via `SarifTool` and `SarifDriver` at lines 80-84), a `results` array containing individual findings, and an optional `artifacts` field.

SkillSpector does not populate the `artifacts` field (defined at lines 92-97), focusing instead on embedding file information within each result's location data.

## Mapping SkillSpector Findings to SARIF Results

### Result Objects and Severity Levels

Individual findings map to `SarifResult` objects, where the `ruleId` field corresponds to `Finding.rule_id` and the `message.text` field contains `Finding.message`. The `_build_sarif` function in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) (lines 5-38) handles this conversion, including severity translation via `_severity_to_sarif_level` (lines 64-71).

This function maps internal severity bands to standard SARIF levels: `"error"`, `"warning"`, or `"note"`.

### Location Information and Physical Regions

Each result contains a `locations` array with `SarifLocation` objects that specify exactly where the issue occurs. The `physicalLocation` contains an `artifactLocation` with a `uri` field, and a `region` object defining the line range.

SkillSpector populates these from `Finding.start_line` and `Finding.end_line` (lines 10-12 in [`report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/report.py)), providing precise file and line coordinates for every vulnerability.

## Generating and Validating SARIF Output

The `report()` function in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) (lines 60-65) returns the final JSON under the key `sarif_report`. Before consumption, you can validate the structure using `validate_sarif_report` (lines 125-128 in [`sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/sarif_models.py)), which uses Pydantic to enforce SARIF 2.1.0 compliance.

The unit tests in [`tests/unit/test_sarif.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/unit/test_sarif.py) (lines 40-74) verify that valid documents round-trip correctly, while lines 105-141 confirm that malformed JSON raises `pydantic.ValidationError`.

## Integrating SkillSpector SARIF with Security Tooling

### Parsing with Pydantic Models

For Python-based integrations, import the models directly from `skillspector.sarif_models` to parse the JSON into typed objects. This approach provides IDE autocomplete and runtime validation, ensuring your integration handles the exact structure SkillSpector emits.

```python
import json
from skillspector.sarif_models import SarifLog, validate_sarif_report

# Assume `sarif_json_str` is the string emitted by SkillSpector

sarif_dict = json.loads(sarif_json_str)

# Validate against the SARIF schema (raises ValidationError if broken)

validate_sarif_report(sarif_dict)

# Parse into strongly-typed objects for convenient access

log = SarifLog.model_validate(sarif_dict)

# Walk through findings

for run in log.runs:
    for result in run.results:
        print(f"Rule: {result.rule_id}")
        print(f"Message: {result.message.text}")
        print(f"Severity: {result.level}")
        for loc in result.locations:
            file_uri = loc.physical_location.artifact_location.uri
            region = loc.physical_location.region
            start = region.start_line if region else "?"
            end = region.end_line if region else start
            print(f"Location: {file_uri}:{start}-{end}")

```

### CI/CD Pipeline Integration

Most modern CI platforms accept SARIF 2.1.0 uploads for security dashboards. You can run SkillSpector with `--output-format sarif` and feed the results directly into actions like `github/codeql-action/upload-sarif`.

```yaml
name: SkillSpector Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run SkillSpector (SARIF output)
        run: |
          pip install skillspector
          skillspector scan . --output-format sarif > skillspector.sarif.json
      - name: Upload SARIF to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: skillspector.sarif.json

```

### Custom Aggregation Scripts

When building internal dashboards, extract specific fields from the validated SARIF log to aggregate findings by rule ID or file path.

```python
def aggregate_by_rule(sarif_dict):
    """Return a dict mapping ruleId → list of (file, line) tuples."""
    log = SarifLog.model_validate(sarif_dict)
    agg = {}
    for result in log.runs[0].results:
        locations = [
            (loc.physical_location.artifact_location.uri,
             loc.physical_location.region.start_line)
            for loc in result.locations
        ]
        agg.setdefault(result.rule_id, []).extend(locations)
    return agg

```

## Summary

- SkillSpector emits standardized SARIF 2.1.0 output defined in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py), ensuring compatibility with security orchestration platforms.
- The `SarifLog` contains `runs` with `results` that map `Finding` objects to SARIF-compliant `ruleId`, `message`, `level`, and `location` fields.
- Use the provided Pydantic models or the `validate_sarif_report` function to ensure output integrity before processing.
- Integration requires extracting the JSON from the `sarif_report` field and iterating over `runs[0].results` to access file paths, line numbers, and severity levels.

## Frequently Asked Questions

### What SARIF version does SkillSpector use?

SkillSpector strictly adheres to SARIF version 2.1.0, as enforced by the `version` field in `SarifLog` and the schema URI `https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json` defined at line 24 of [`sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/sarif_models.py).

### How does SkillSpector map severity levels to SARIF?

The internal `_severity_to_sarif_level` function in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) (lines 64-71) translates SkillSpector's native severity bands to standard SARIF levels: `"error"` for high severity, `"warning"` for medium, and `"note"` for informational findings.

### Can I validate SkillSpector SARIF output against the official schema?

Yes. The `validate_sarif_report` function in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py) (lines 125-128) uses Pydantic validation to ensure the output conforms to the SARIF 2.1.0 specification, raising `ValidationError` for malformed documents as tested in [`tests/unit/test_sarif.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/unit/test_sarif.py).

### Where does the artifact location information come from in SkillSpector results?

The file paths and line numbers originate from `Finding.start_line` and `Finding.end_line` attributes, which the `_build_sarif` function (lines 10-12 in [`report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/report.py)) maps to the `physicalLocation.artifactLocation.uri` and `region` fields within each `SarifResult`.