How to Integrate SkillSpector into CI/CD Pipelines for SARIF Output

You can integrate SkillSpector into CI/CD pipelines by invoking the CLI with --format sarif and uploading the generated JSON file to compatible platforms like GitHub Actions, Azure Pipelines, or GitLab CI, which automatically annotate pull requests with security findings.

NVIDIA/SkillSpector is a static analysis tool that generates SARIF 2.1.0 (Static Analysis Results Interchange Format) output, the industry standard for security scan results. This guide explains how to configure SkillSpector to produce SARIF reports and integrate them into continuous integration workflows using the source code architecture found in src/skillspector/cli.py and src/skillspector/nodes/report.py.

Understanding the SARIF Generation Pipeline

SkillSpector implements a LangGraph-based workflow that transforms security findings into standardized SARIF documents through three distinct stages.

CLI Initialization and State Configuration

When you execute skillspector scan --format sarif, the CLI entry point in src/skillspector/cli.py (lines 95-101) parses the flag and initializes the graph state with "output_format": "sarif". This _scan_state dictionary propagates through the entire workflow, signaling downstream nodes to structure output accordingly.

Graph Execution and Finding Collection

The graph.invoke method orchestrates a series of analyzer nodes—including static pattern matchers, optional LLM semantic checks, and OSV lookups—that collect vulnerabilities into a filtered_findings list within the state object. Each finding follows the Finding data class defined in src/skillspector/models.py, containing rule IDs, severity levels, and precise file locations.

Report Node and SARIF Serialization

The report node in src/skillspector/nodes/report.py (lines 48-66) calls _build_sarif to transform findings into SARIF-compliant objects. This function iterates over each Finding, creates a SarifResult with mapped severity levels, and assembles a SarifLog using Pydantic models from src/skillspector/sarif_models.py. The final payload is serialized via model_dump(..., by_alias=True) and returned as sarif_report in the node's output dictionary.

In cli.py, the _write_result helper detects the SARIF format and writes the JSON payload using json.dumps(..., indent=2), producing a file that CI/CD systems can ingest directly.

CI/CD Integration Examples

GitHub Actions Workflow

GitHub Actions can upload SARIF files to Code Scanning, which automatically creates security alerts and annotates pull requests.

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: Export LLM env vars
        env:
          SKILLSPECTOR_PROVIDER: ${{ secrets.SKILLSPECTOR_PROVIDER }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          echo "SKILLSPECTOR_PROVIDER=${SKILLSPECTOR_PROVIDER}" >> $GITHUB_ENV
          echo "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}" >> $GITHUB_ENV

      - 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 creates Code Scanning alerts from skill_report.sarif without additional configuration.

Azure Pipelines Configuration

Azure DevOps supports SARIF ingestion through the Publish Test Results task.

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 Integration

GitLab's security reports UI renders SARIF findings automatically when declared as job artifacts.

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

Python API for Custom Pipelines

For advanced workflows, invoke SkillSpector programmatically without shelling out to the CLI.

from skillspector import graph
import json
import pathlib

# Configure the initial state with SARIF output format

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

}

# Execute the analysis workflow

result = graph.invoke(state)

# Extract the SARIF document as a Python dictionary

sarif_report = result["sarif_report"]

# Write to file for downstream CI consumption

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

This approach bypasses the CLI's _write_result logic while producing identical output compatible with sarif_models.py definitions.

Automating Pipeline Failures

SkillSpector supports automatic pipeline failure based on risk thresholds. When the aggregated risk_score across all findings exceeds 50, the CLI exits with a non-zero status code. This behavior enables you to block merges or deployments when critical vulnerabilities are detected without parsing the SARIF file manually.

To leverage this in your CI configuration, simply run the scan step without error suppression. The non-zero exit code will fail the job stage automatically.

Summary

  • Use --format sarif to generate SARIF 2.1.0 output that GitHub Actions, Azure Pipelines, and GitLab CI can ingest natively.
  • The report node in src/skillspector/nodes/report.py constructs findings using Pydantic models from src/skillspector/sarif_models.py, ensuring strict schema compliance.
  • CI platforms automatically annotate pull requests and generate security dashboards when you upload the SARIF file to their respective upload tasks or artifact reports.
  • Risk-based failures occur automatically when SkillSpector calculates a risk_score greater than 50, enabling pipeline gating without custom scripts.

Frequently Asked Questions

What SARIF version does SkillSpector generate?

SkillSpector generates SARIF 2.1.0 output according to the OASIS standard. The Pydantic models in src/skillspector/sarif_models.py define the schema structure, including required fields like tool.driver, runs, and results arrays.

How do I configure a CI job to fail when SkillSpector finds critical vulnerabilities?

SkillSpector automatically exits with a non-zero status code when the aggregated risk_score exceeds 50. Your CI pipeline will fail the stage automatically if you run the scan without error suppression, making it unnecessary to parse the SARIF file for threshold checks.

Can I integrate SkillSpector into CI/CD without using the CLI?

Yes. You can import the graph module from src/skillspector/graph.py and invoke graph.invoke() directly with an output_format key set to "sarif". This Python API approach returns a dictionary containing the sarif_report key, which you can serialize and handle programmatically within custom pipeline scripts.

Where in the source code is the SARIF output actually formatted?

The SARIF document is constructed in src/skillspector/nodes/report.py within the _build_sarif function, which converts Finding objects into SarifResult instances. The final JSON serialization occurs in src/skillspector/cli.py inside the _write_result helper, which uses json.dumps to format the Pydantic model output (via model_dump) with indentation for file writing.

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 →