# How to Integrate SkillSpector into CI/CD Pipelines for Automated Security Scanning

> Seamlessly integrate SkillSpector into your CI/CD pipelines for automated security scanning. Run the CLI with SARIF output and upload results to your security dashboard for fast static-only scans on every commit.

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

---

**Integrate SkillSpector into CI/CD pipelines by running the CLI with SARIF output (`-f sarif`) and uploading the resulting `.sarif` file to your platform's security dashboard, using `--no-llm` for fast static-only scans on every commit.**

SkillSpector is an open-source Python security scanner from NVIDIA that analyzes AI-agent skill packages to detect vulnerabilities and supply-chain risks. Integrating it into your continuous integration workflows ensures every code change is automatically vetted for security issues before deployment. This guide covers the architecture, source code integration points, and practical implementations for GitHub Actions, GitLab CI, and other platforms.

## Understanding SkillSpector's Architecture for CI/CD Integration

SkillSpector is built around a two-stage **LangGraph workflow** that produces machine-readable security reports. Understanding these stages helps you optimize CI performance.

### Static Analysis Stage

The first stage performs fast, deterministic analysis using regex-driven pattern matching, AST inspection, and live OSV vulnerability lookups. This stage is implemented in [`src/skillspector/graph.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/graph.py) and executes quickly without external API dependencies, making it ideal for per-commit CI runs.

### Optional LLM Semantic Analysis

The second stage uses language models (OpenAI, Anthropic, or NVIDIA) to validate static findings and reduce false positives. While this improves accuracy, it adds latency and requires API credentials. In `src/skillspector/providers/`, the provider adapters handle credential lookup via environment variables like `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.

### SARIF Output Format

SkillSpector outputs **SARIF 2.1** (Static Analysis Results Interchange Format) via [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py), which serializes findings into the standard JSON schema that GitHub, GitLab, Azure DevOps, and other platforms natively consume. The CLI can generate multi-run SARIF files where the first run contains static findings and a second run (when enabled) contains LLM-validated findings.

## Key Integration Points in the Source Code

Before configuring your pipeline, understand these critical components:

- **[`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py)**: Parses command-line arguments, builds the initial graph state, and writes the final report. The `scan` command handles the `-f sarif` flag to output CI-compatible files.
- **[`src/skillspector/graph.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/graph.py)**: Instantiates the LangGraph workflow, orchestrates static and optional LLM nodes, and returns a dictionary containing `report_body` and `sarif_report`.
- **[`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py)**: Converts internal finding objects into compliant SARIF JSON attached to `result["sarif_report"]`.
- **[`src/skillspector/constants.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/constants.py)**: Defines risk-scoring values, severity thresholds, and static pattern IDs used to categorize findings.

## Step-by-Step CI/CD Integration Guide

### GitHub Actions Workflow (Static Only)

For deterministic, fast feedback on every push, run static analysis without LLM validation. Use the `github/codeql-action/upload-sarif` action to surface findings in the Security tab.

```yaml
name: SkillSpector 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 (with Optional LLM)

Configure conditional logic to enable LLM analysis only when API keys are present, falling back to static-only for standard merge request pipelines.

```yaml
skillsspector_scan:
  image: python:3.12-slim
  stage: test
  script:
    - pip install --no-cache-dir skillspector
    - |
      # Enable LLM analysis if ANTHROPIC_API_KEY is set in CI variables

      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

```

### Azure Pipelines and Other Platforms

For Azure DevOps, use the `PublishSecurityAnalysisLogs@3` task after generating the SARIF file:

```yaml
steps:
  - script: |
      pip install skillspector
      skillspector scan . -f sarif -o report.sarif --no-llm
    displayName: 'Run SkillSpector Security Scan'

  - task: PublishSecurityAnalysisLogs@3
    inputs:
      ArtifactName: 'CodeAnalysisLogs'
      ArtifactType: 'Container'

```

### Docker-Based Integration

If your CI runners lack Python, use a Docker container to mount the repository and output the SARIF file:

```bash
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.

### Programmatic Python API Integration

For advanced workflows, invoke the LangGraph workflow directly from Python scripts:

```python
from skillspector.graph import graph

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 later upload

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

```

## Optimizing Scan Performance in CI Environments

**Static-only mode** (`--no-llm`) provides sub-second execution for most skill packages, making it suitable for pre-commit or pre-merge checks. The static analysis engine in [`src/skillspector/graph.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/graph.py) performs local regex and AST operations without network latency.

**LLM-enhanced scans** should be scheduled as nightly workflows or scheduled pipelines. When `use_llm` is enabled, the graph invokes provider-specific clients from `src/skillspector/providers/` to validate findings, which introduces non-deterministic latency based on API response times.

Set the `SKILLSPECTOR_PROVIDER` environment variable to select your LLM backend, and ensure corresponding API keys (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or NVIDIA equivalents) are stored in your CI platform's secret management system.

## Summary

- **SARIF output** (`-f sarif`) is the standard integration format consumed by GitHub Code Scanning, GitLab SAST, and Azure DevOps security dashboards.
- **Static analysis** (`--no-llm`) runs fast and requires no API credentials, making it ideal for per-commit CI jobs.
- **Core files**: [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) handles CLI execution, [`src/skillspector/graph.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/graph.py) orchestrates the workflow, and [`src/skillspector/sarif_models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/sarif_models.py) generates compliant reports.
- **Docker containers** provide a Python-free option for minimal CI runners.
- **Programmatic access** via `graph.invoke()` allows custom CI scripts to manipulate results before upload.

## Frequently Asked Questions

### What is the recommended way to run SkillSpector in GitHub Actions?

Run SkillSpector with the `--no-llm` flag for speed, output SARIF format, and use the `github/codeql-action/upload-sarif` action to upload results. This surfaces security alerts directly in your repository's Security tab and pull request checks without requiring external API keys.

### Does SkillSpector support GitLab's built-in SAST dashboard?

Yes. SkillSpector generates SARIF 2.1 compliant output that GitLab CI can ingest via the `artifacts:reports:sast` keyword. Configure your job to output `report.sarif` and GitLab will automatically parse severity levels and locations, displaying them in the merge request security widget.

### How do I handle API keys for LLM analysis in CI environments?

Store provider credentials (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.) in your CI platform's secret variables. In your pipeline script, export these as environment variables and set `SKILLSPECTOR_PROVIDER` to the appropriate provider name. For security, only enable LLM analysis in scheduled pipelines or protected branches, using static-only scans for standard merge requests.

### Can I use SkillSpector without installing Python on my CI runner?

Yes. Build a Docker image containing SkillSpector and run it as a container step, mounting your repository as a volume. The container outputs the SARIF file to the mounted directory, which persists after the container exits for upload to your security dashboard.