How to Integrate SkillSpector into a CI/CD Pipeline for Automated Security Scanning

Integrate SkillSpector into your CI/CD pipeline by installing the Python package, running skillspector scan with SARIF output format, and uploading the resulting .sarif file to your platform's security dashboard.

SkillSpector is an open-source security scanner developed by NVIDIA that analyzes AI-agent skill packages—including SKILL.md files, source code, and dependencies—to generate risk scores and remediation guidance. Adding automated security scans to your continuous integration workflow ensures that every commit is validated against vulnerability patterns before deployment.

Understanding SkillSpector's Architecture for CI/CD Integration

SkillSpector is built around a LangGraph workflow that orchestrates two distinct analysis stages. According to the NVIDIA/SkillSpector source code, this design enables flexible execution modes suitable for fast CI checks and comprehensive security audits.

Core Components

The integration relies on three primary source files:

  • src/skillspector/cli.py – Parses command-line arguments, constructs the initial graph state, and handles report serialization including SARIF generation.
  • src/skillspector/graph.py – Instantiates the LangGraph workflow, executes static and optional LLM analysis nodes, and returns a dictionary containing report_body and sarif_report.
  • src/skillspector/sarif_models.py – Implements the SARIF 2.1 schema, converting internal findings into the standardized JSON format that CI platforms consume.

Additional supporting modules include src/skillspector/providers/ (LLM adapters for OpenAI, Anthropic, and NVIDIA) and src/skillspector/constants.py (risk-scoring thresholds and pattern definitions).

The Two-Stage Analysis Workflow

SkillSpector executes security checks through two sequential stages:

  1. Static Analysis – Fast regex-driven pattern matching, AST inspection, and live OSV vulnerability lookups. This stage is deterministic, requires no external API calls (except OSV lookups), and completes in seconds.
  2. Optional LLM Semantic Analysis – A language-model validation step that reviews static findings to reduce false positives. Enabled when --no-llm is omitted and provider credentials are configured via environment variables (SKILLSPECTOR_PROVIDER, OPENAI_API_KEY, etc.).

Both stages populate a unified result object that the CLI formats into terminal, JSON, Markdown, or SARIF output.

Generating SARIF Reports for CI Platforms

SARIF (Static Analysis Results Interchange Format) is the standard exchange format for static analysis tools. SkillSpector emits a multi-run SARIF document where the first run contains static findings and a second run (when LLM analysis is enabled) contains dynamic findings. This structure allows security dashboards to display provenance information for each vulnerability.

To generate SARIF output, use the -f or --format flag combined with an output file:

skillspector scan . -f sarif -o report.sarif --no-llm

The resulting file adheres to the SARIF 2.1 schema and can be consumed directly by GitHub Advanced Security, GitLab SAST dashboards, Azure DevOps security reports, and other SARIF-compatible platforms.

Step-by-Step CI/CD Integration

1. Install SkillSpector

Install the package via pip or use a container image. For Python-based workflows:

pip install skillspector

For Docker-based workflows, build from the repository or use a pre-built image mounting your source code as a volume.

2. Execute the Security Scan

Run the scan against your skill package directory. For CI environments, use static-only mode (--no-llm) to ensure fast, deterministic results without external API dependencies:

skillspector scan ./my-skill -f sarif -o report.sarif --no-llm

If your pipeline requires deeper semantic analysis, omit --no-llm and ensure the appropriate provider API key is available via environment variables.

3. Upload SARIF to Your Platform

Upload the generated report.sarif to your CI platform's security reporting service:

  • GitHub Actions: Use github/codeql-action/upload-sarif or the native upload-sarif action.
  • GitLab CI: Configure artifacts:reports:sast in your job definition.
  • Azure Pipelines: Use the PublishSecurityAnalysisLogs@3 task.

CI/CD Implementation Examples

GitHub Actions Workflow (Static Only)

This workflow triggers on commits affecting skill files, runs a static-only scan, and uploads results to GitHub Code Scanning:

name: SkillSpector Security Scan

on:
  push:
    paths:
      - '**.md'
      - '**.py'
      - '**/requirements.txt'

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        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

      - name: Run static scan and generate SARIF
        run: |
          skillspector scan . -f sarif -o report.sarif --no-llm

      - name: Upload SARIF to GitHub Code Scanning
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: report.sarif

GitLab CI Configuration (Conditional LLM)

This example conditionally enables LLM analysis if the ANTHROPIC_API_KEY variable is present, otherwise falling back to static-only mode:

skillsspector_scan:
  image: python:3.12-slim
  stage: test
  script:
    - pip install --no-cache-dir skillspector
    - |
      if [ -n "$ANTHROPIC_API_KEY" ]; then
        export SKILLSPECTOR_PROVIDER=anthropic
        skillspector scan . -f sarif -o report.sarif
      else
        skillspector scan . -f sarif -o report.sarif --no-llm
      fi
  artifacts:
    reports:
      sast: report.sarif
    expire_in: 1 week

Python API Integration

For custom CI scripts, invoke the LangGraph workflow directly via the Python API:

from skillspector.graph import graph
import json

result = graph.invoke({
    "input_path": "./my-skill",
    "output_format": "sarif",
    "use_llm": False,  # Static-only for CI speed

})

# Write the SARIF payload to a file for upload

with open("report.sarif", "w", encoding="utf-8") as f:
    json.dump(result["sarif_report"], f, indent=2)

Docker-Based Scanning

Run SkillSpector without installing Python on the host runner:

docker build -t skillspector .
docker run --rm \
  -v "$(pwd)":/scan \
  -e SKILLSPECTOR_PROVIDER=openai \
  -e OPENAI_API_KEY="${OPENAI_API_KEY}" \
  skillspector scan /scan --format sarif --output /scan/report.sarif

After the container exits, report.sarif is available in the repository root for upload to your security dashboard.

Optimizing Scan Performance in CI Environments

For optimal CI/CD performance, adopt a tiered scanning strategy:

  • Per-commit scans: Run static-only analysis (--no-llm) for fast feedback on every pull request. This mode executes regex patterns, AST inspection, and OSV lookups without external LLM latency.
  • Scheduled deep scans: Configure nightly or weekly workflows that enable LLM semantic analysis (--dynamic or omit --no-llm) for comprehensive false-positive reduction and complex vulnerability detection.

Static scans typically complete in seconds, while LLM-enhanced scans depend on API response times and token processing. The src/skillspector/graph.py implementation ensures that enabling the LLM stage only extends the workflow when explicitly configured, preserving CI speed for standard development cycles.

Summary

  • SkillSpector integrates into CI/CD pipelines via SARIF output, consumed by GitHub Actions, GitLab CI, and Azure Pipelines.
  • The static analysis stage (--no-llm) provides fast, deterministic security checks suitable for per-commit validation.
  • SARIF reports are generated using skillspector scan -f sarif -o report.sarif and uploaded via platform-specific actions or tasks.
  • Key source files include src/skillspector/cli.py (CLI wrapper), src/skillspector/graph.py (workflow orchestration), and src/skillspector/sarif_models.py (format serialization).
  • For programmatic integration, use graph.invoke() with use_llm=False to generate SARIF payloads in Python scripts.

Frequently Asked Questions

What is the difference between static and LLM analysis in SkillSpector?

Static analysis uses regex patterns, AST inspection, and OSV database lookups to identify vulnerabilities rapidly without external dependencies. LLM analysis adds a semantic validation layer where language models evaluate static findings to reduce false positives and detect complex logic flaws. Static analysis runs by default; LLM analysis requires provider credentials and is enabled by omitting the --no-llm flag.

Why should I use SARIF format instead of JSON for CI integration?

SARIF is the industry-standard format for static analysis results, designed specifically for interoperability between security tools and CI platforms. While SkillSpector supports JSON output, SARIF files are natively consumed by GitHub Advanced Security, GitLab SAST dashboards, and Azure DevOps security reports, enabling automatic mapping of findings to specific code locations and severity levels without custom parsing.

How do I handle LLM provider credentials securely in CI pipelines?

Store API keys as encrypted CI/CD variables (GitHub Secrets, GitLab CI/CD Variables, or Azure Pipeline Secrets) and reference them via environment variables. SkillSpector reads credentials from standard environment variables like OPENAI_API_KEY, ANTHROPIC_API_KEY, or NVIDIA_API_KEY, and selects the provider via SKILLSPECTOR_PROVIDER. Never commit credentials to repository files.

Can I run SkillSpector without installing Python on my CI runners?

Yes. SkillSpector can run inside a Docker container. Build the image from the repository or use a pre-built version, mount your source code as a volume, and execute the scan command. The SARIF output is written to the mounted volume, making the report available to the CI runner for upload without requiring Python on the host system.

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 →