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 sarifto 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.pyconstructs findings using Pydantic models fromsrc/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_scoregreater 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →