How to Interpret SARIF Output for CI/CD Integration with NVIDIA SkillSpector

SkillSpector generates validated SARIF 2.1.0 reports that map security findings directly to CI/CD alert levels, enabling automated build failures and security gates through standard JSON parsing.

NVIDIA SkillSpector analyzes code for security vulnerabilities and outputs results in the Static Analysis Results Interchange Format (SARIF). Understanding how to interpret SARIF output for CI/CD integration allows you to automate security scanning in GitHub Actions, Azure Pipelines, and other DevOps platforms without custom parsers.

Understanding SkillSpector's SARIF Schema

SkillSpector implements the SARIF 2.1.0 standard, producing JSON-compatible reports that follow the official schema. In src/skillspector/nodes/report.py, the _build_sarif function constructs the document by converting internal Finding objects into standardized SARIF structures.

Core SARIF Structure

The generated SARIF document contains:

  • $schema: Points to the official SARIF 2.1.0 schema URL
  • runs: Array containing a single run object (one SkillSpector invocation)
  • tool.driver: Identifies SkillSpector name and version for traceability
  • results: Array of finding objects, each representing a detected security issue

The SarifLog Model

The underlying data structure is defined in src/skillspector/sarif_models.py as the SarifLog Pydantic model. This model validates the final output through validate_sarif_report before serialization, ensuring CI/CD systems receive schema-compliant JSON.

Mapping Severity Levels for CI/CD Alerts

SkillSpector maps its internal severity bands to SARIF's level field for standardized CI/CD consumption:

  • CRITICAL/HIGH → error (fails builds)
  • MEDIUM → warning (visible alerts)
  • LOW → note (informational)

This mapping occurs in the report generation logic within _build_sarif, allowing CI/CD platforms to render appropriate visual badges and set failure thresholds without custom parsing logic.

Locating Issues in Source Code

Each result entry contains precise location data through nested objects:

  • ruleId: The SkillSpector analyzer identifier (e.g., TP001, ASV02)
  • locations: Array containing physicalLocation objects
    • artifactLocation.uri: Relative file path
    • region: Optional line numbers (startLine, endLine)

This structure enables CI/CD systems to annotate pull requests with exact file and line references.

CI/CD Integration Examples

GitHub Actions Workflow

Upload SkillSpector results to GitHub Code Scanning using the official CodeQL action:

name: SkillSpector Scan
on: [push, pull_request]

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

Azure Pipelines Integration

Publish results as test artifacts using the PublishTestResults task:

steps:
- script: |
    pip install skillspector
    skillspector scan . --output-format sarif > $(Build.ArtifactStagingDirectory)/sarif.json
  displayName: Run SkillSpector

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

Parsing SARIF in Python

Extract findings programmatically for custom CI/CD logic:

import json
from pathlib import Path

sarif_path = Path("output/sarif.json")
sarif = json.loads(sarif_path.read_text())

for run in sarif["runs"]:
    for result in run["results"]:
        rule = result["ruleId"]
        level = result["level"]
        loc = result["locations"][0]["physicalLocation"]["artifactLocation"]["uri"]
        region = result["locations"][0]["physicalLocation"].get("region", {})
        start = region.get("startLine", "?")
        end = region.get("endLine", start)
        print(f"{rule}: {level.upper()} in {loc}:{start}-{end}")

Generic CI/CD Upload

For platforms with SARIF endpoints:


# Generate SARIF

pip install skillspector
skillspector scan . --output-format sarif > sarif.json

# Upload to CI endpoint

curl -X POST -H "Content-Type: application/json" \
     --data @sarif.json \
     https://ci.example.com/api/upload-sarif

Summary

  • SkillSpector generates SARIF 2.1.0 output through the _build_sarif function in src/skillspector/nodes/report.py
  • The SarifLog model in src/skillspector/sarif_models.py validates results against the official schema using validate_sarif_report
  • Severity maps to standard level values (error, warning, note) for immediate CI/CD consumption
  • Each result contains ruleId and physicalLocation data for precise file and line identification
  • Validated SARIF output works natively with GitHub Actions, Azure Pipelines, and GitLab SAST without transformation

Frequently Asked Questions

What SARIF version does SkillSpector use?

SkillSpector implements SARIF 2.1.0 (RTM.4), referencing the official schema at https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json. This version is the de-facto standard for static analysis tools and is supported by all major CI/CD platforms including GitHub Code Scanning and Azure DevOps.

How does SkillSpector map internal severity to SARIF levels?

The conversion happens in src/skillspector/nodes/report.py. Critical and High severity findings map to error, Medium to warning, and Low to note. This mapping allows CI/CD systems to apply standard failure thresholds without custom configuration.

Where is the SARIF generation logic located in the SkillSpector codebase?

The core logic resides in src/skillspector/nodes/report.py within the _build_sarif method, which converts internal Finding objects (defined in src/skillspector/models.py) into SARIF-compliant structures. The Pydantic models for the SARIF schema are defined in src/skillspector/sarif_models.py.

Can SkillSpector SARIF output trigger automated build failures?

Yes. Because SkillSpector emits valid SARIF with appropriate level fields, CI/CD platforms like GitHub Actions and Azure DevOps automatically fail pipelines when error level results are present. You can also parse the JSON programmatically using the results array to implement custom gating logic based on specific ruleId patterns or severity thresholds.

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 →