# How to Integrate NVIDIA SkillSpector into CI/CD Pipelines Using SARIF Output

> Integrate NVIDIA SkillSpector into CI CD pipelines with SARIF output. Automate code scanning and get security findings directly in your pull requests.

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

---

**You can integrate SkillSpector into CI/CD pipelines by invoking `skillspector scan --format sarif` to generate a SARIF 2.1.0 file, then uploading that report to your platform's code scanning service to automatically annotate pull requests with security findings.**

NVIDIA SkillSpector is a specialized static analysis tool designed for evaluating AI skill definitions and code patterns. When you integrate SkillSpector into CI/CD pipelines using SARIF output, you enable automated security scanning that feeds directly into native code scanning dashboards, allowing teams to catch vulnerabilities before they reach production.

## Understanding SkillSpector's SARIF Architecture

SkillSpector's reporting pipeline is built around a `report` node that produces a SARIF 2.1.0 document. This standardized format allows CI/CD systems including GitHub Actions, Azure Pipelines, and GitLab CI to ingest findings directly without custom parsing logic.

### From CLI Arguments to Graph State

The integration begins in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) where the `skillspector scan` command parses the `--format` flag. When the value is `sarif`, the CLI stores `"output_format": "sarif"` in the initial graph state within the `_scan_state` dictionary (lines 95-101). This state object persists through the LangGraph workflow execution.

The `graph.invoke()` method orchestrates a series of analyzer nodes—including static pattern matchers, optional LLM semantic checks, and OSV lookups—that collect findings into the `filtered_findings` state field.

### SARIF Generation in the Report Node

The **report** node in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) (lines 48-66) handles the actual transformation. The `report()` function reads the accumulated findings and calls `_build_sarif`, which iterates over each `Finding` object and creates a `SarifResult` containing:

- **Rule ID** mapping to the specific vulnerability pattern
- **Message** describing the finding
- **Severity level** mapped to SARIF's standardized levels
- **File location** with precise line and column ranges

The `_build_sarif` function assembles a `SarifLog` object using the Pydantic models defined in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py), then serializes it to a plain Python dictionary via `model_dump(..., by_alias=True)`.

### Output Handling and Persistence

In the CLI's `_write_result` helper ([`cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/cli.py)), when the selected format is SARIF, the `report_body` contains the raw SARIF dictionary. The CLI writes this as a pretty-printed JSON file using `json.dumps(..., indent=2)`, ensuring the output is human-readable while remaining machine-parseable.

## CI/CD Integration Examples

Because the SARIF payload is a plain JSON object, it integrates seamlessly with major CI/CD platforms. Each platform can ingest the `report.sarif` file to create security dashboards and block merges based on detected risk.

### GitHub Actions with Code Scanning

GitHub's Code Scanning API natively understands SARIF 2.1.0. Use the `github/codeql-action/upload-sarif` action to automatically create alerts from your SkillSpector findings.

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

jobs:
  scan-skill:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install SkillSpector
        run: |
          python -m pip install --upgrade pip
          pip install skillspector[all]

      - name: Run SkillSpector (SARIF)
        id: scan
        run: |
          skillspector scan . \
            --format sarif \
            --output skill_report.sarif

      - name: Upload SARIF report
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: skill_report.sarif

```

The `upload-sarif` action automatically creates Code Scanning alerts visible in the Security tab and annotates pull request files with inline comments.

### Azure Pipelines Configuration

Azure DevOps can publish SARIF files as test results using the `PublishTestResults@2` task with the SARIF format.

```yaml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: |
    python -m pip install --upgrade pip
    pip install skillspector[all]
  displayName: 'Install SkillSpector'

- script: |
    skillspector scan $(Build.SourcesDirectory) \
      --format sarif \
      --output $(Build.ArtifactStagingDirectory)/skill.sarif
  displayName: 'Run SkillSpector'

- task: PublishTestResults@2
  inputs:
    testResultsFormat: 'SARIF'
    testResultsFiles: '$(Build.ArtifactStagingDirectory)/skill.sarif'
    mergeTestResults: true

```

### GitLab CI Security Reports

GitLab's Security Reports UI renders SARIF findings automatically when you specify the `sarif` report type in your job artifacts.

```yaml
stages:
  - scan

skill_scan:
  image: python:3.12-slim
  stage: scan
  script:
    - pip install skillspector[all]
    - skillspector scan $CI_PROJECT_DIR --format sarif --output skill.sarif
  artifacts:
    paths:
      - skill.sarif
    reports:
      sarif: skill.sarif

```

### Programmatic Integration via Python API

For custom pipeline scripts, invoke SkillSpector directly through its Python API without shelling out to the CLI.

```python
from skillspector import graph
import json
import pathlib

# Build the initial state with SARIF output format

state = {
    "input_path": "/path/to/skill",
    "output_format": "sarif",
    "use_llm": False,  # Static-only for faster CI execution

}

# Execute the full analysis workflow

result = graph.invoke(state)

# Extract the SARIF document as a dictionary

sarif_report = result["sarif_report"]

# Write to file for downstream CI consumption

path = pathlib.Path("skill_report.sarif")
path.write_text(json.dumps(sarif_report, indent=2))
print(f"SARIF saved to {path}")

```

## Configuring Pipeline Failures and Risk Thresholds

SkillSpector supports deterministic pipeline gating through exit codes. According to the source implementation in [`cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/cli.py), the scanner exits with a non-zero status when the aggregated `risk_score` exceeds 50, allowing you to fail builds automatically based on severity thresholds.

You can also parse the SARIF output programmatically to implement custom logic. The SARIF log contains a top-level `runs` array with a single run, a `tool.driver` entry identifying SkillSpector, and a `results` list where each entry maps to a specific finding with its severity level.

## Summary

- **SARIF 2.1.0 Standard**: SkillSpector generates standardized SARIF output via [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py), enabling direct integration with GitHub, Azure, and GitLab security dashboards.
- **CLI Integration**: Use `skillspector scan --format sarif --output report.sarif` to generate machine-readable scan results.
- **Python API**: The `graph.invoke()` method accepts an `output_format` parameter, returning SARIF data as a dictionary via the `sarif_report` key.
- **Pipeline Gating**: The tool exits with non-zero status when `risk_score > 50`, enabling automatic build failure for high-risk findings.
- **Source References**: Key files include [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) (CLI handling), [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) (SARIF construction), and [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py) (Pydantic schema definitions).

## Frequently Asked Questions

### What is SARIF and why does SkillSpector use it?

SARIF (Static Analysis Results Interchange Format) is an OASIS standard JSON schema designed for static analysis tools. SkillSpector uses SARIF 2.1.0 because it provides a standardized way to represent findings with precise file locations, severity levels, and rule metadata. This allows CI/CD platforms like GitHub and GitLab to ingest results natively without requiring custom parsers or adapters.

### How do I fail a CI pipeline based on SkillSpector findings?

SkillSpector automatically exits with a non-zero status code when the aggregate `risk_score` exceeds 50, which fails the CI job immediately. For custom thresholds, parse the generated SARIF file and inspect the `results` array. Each result contains a `level` property (error, warning, note) that you can evaluate against your organization's quality gates using a simple script in your pipeline.

### Can I use SkillSpector without installing Python in my CI environment?

Currently, SkillSpector requires Python 3.12 or later to run. You must install it via `pip install skillspector[all]` in your CI environment. The `[all]` extra includes dependencies necessary for full SARIF generation and LLM integration. Container-based CI jobs can use the `python:3.12-slim` image or a custom image with SkillSpector pre-installed to avoid repeated installations.

### Where are the SARIF Pydantic models defined in the source code?

The SARIF schema definitions are located in [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py). This file contains Pydantic models for `SarifLog`, `SarifRun`, `SarifResult`, and related structures that validate the output against the SARIF 2.1.0 specification. The `report()` node in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) uses these models to construct the final document before serialization.