skillguard-core
Security scanner for AI agent skills. Wraps NVIDIA SkillSpector and Cisco skill-scanner, fuses their findings into a verdict, and reports via JSON, SARIF, or CI exit codes. Apache-2.0.
Part of SkillGuard — continuous trust for AI agent skills. Hosted drift monitoring and CI policy live at skillguard.dev.
How it works
The scanner follows a deterministic pipeline — no agent framework on the hot path:
fetch → engines → fuse → (optional: semantic review) → report
-
Ingest (
ingest/fetcher.py) — Fetches a skill from a local directory, Git URL, or zip URL. A directory of skills (subdirs with SKILL.md) is scanned in batch with a progress bar. -
Engines (
engines/) — Runs two open-source scanners as subprocesses:- NVIDIA SkillSpector — Heuristic+LLM-aware static analysis
- Cisco skill-scanner — Policy-based static analysis
- Runners are injectable — unit tests work without real binaries.
-
Fusion (
engines/fusion.py) — Conservative scoring: takes the max of the engine's risk score and individual finding severities. Verdicts:safe(<30),caution(30–69),dangerous(≥70). Partial engine failures are surfaced but don't block the verdict. -
Semantic review (
semantic/reviewer.py) — Optional Deep Agents pass triggered oncautionanddangerousverdicts (not safe). Supports Anthropic natively or any OpenAI-compatible provider viaLLM_API_KEY+LLM_BASE_URL. -
Report — The
ScanReportdataclass (pipeline/scan.py) is storage-agnostic: no database, no persistence — the private repo plugs in a store.
Install
# Scanner engines (required)
uv tool install git+https://github.com/NVIDIA/skillspector.git
uv tool install git+https://github.com/cisco-ai-defense/skill-scanner.git
# CLI
pipx install skillguard-core # from PyPI (once published)
pipx install "git+https://github.com/AI-Provenance/skillguard-core.git@v0.1.7" # from git
For LLM review, install with the ai extra:
pipx install "skillguard-core[ai]"
Usage
# Single skill
skillguard scan ./my-skill # human output
skillguard scan ./my-skill --json # machine output
skillguard scan ./my-skill --sarif # SARIF 2.1.0
# Directory of skills (batch)
skillguard scan ./skills # progress bar + summary
skillguard scan ./skills -v # verbose: stream results as they complete
skillguard scan ./skills -w 8 # 8 parallel workers (default: CPU count)
# LLM review (second opinion on caution/dangerous verdicts)
skillguard scan ./my-skill --use-llm # needs ANTHROPIC_API_KEY or LLM_API_KEY+LLM_BASE_URL
Exit codes: 0 safe · 1 caution · 2 dangerous · 3 inconclusive/error.
LLM Provider Setup
Anthropic (native structured output):
export SKILLGUARD_ANTHROPIC_API_KEY=sk-ant-...
export SKILLGUARD_SEMANTIC_MODEL=claude-sonnet-4-5 # default
Any OpenAI-compatible provider (Ollama, vLLM, Groq, DeepSeek, etc.):
export SKILLGUARD_LLM_API_KEY=sk-...
export SKILLGUARD_LLM_BASE_URL=https://api.groq.com/openai/v1
export SKILLGUARD_SEMANTIC_MODEL=llama-3.3-70b
GitHub Action
name: Scan skills
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install scanner engines
run: |
pipx install git+https://github.com/NVIDIA/skillspector.git
pipx install git+https://github.com/cisco-ai-defense/skill-scanner.git
- uses: AI-Provenance/skillguard-core@v0.1.7
with:
path: skills/
fail-on: dangerous # or "caution" to fail on any warning
workers: "8" # parallel workers (default: CPU count)
use-llm: "true" # optional: LLM review of caution/dangerous verdicts
env:
# Bring your own key — never pass secrets as `with:` inputs.
# Anthropic:
SKILLGUARD_ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# Model used for LLM review — always match it to your provider
# (the Anthropic default is claude-sonnet-4-5):
SKILLGUARD_SEMANTIC_MODEL: claude-sonnet-4-5
# or any OpenAI-compatible provider:
# SKILLGUARD_LLM_API_KEY: ${{ secrets.SKILLGUARD_LLM_API_KEY }}
# SKILLGUARD_LLM_BASE_URL: https://api.groq.com/openai/v1
# SKILLGUARD_SEMANTIC_MODEL: llama-3.3-70b
# Uploads the SARIF to GitHub Code Scanning. The action itself only
# stores skillguard.sarif as a workflow artifact for download/debug.
# `if: always()` keeps this running when the scan step fails (e.g.
# dangerous skills found) — that's when you most want the results.
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: skillguard.sarif
The action stores skillguard.sarif at the workspace root as a workflow
artifact (for download/debug), even when the scan fails. The separate
codeql-action/upload-sarif step above is what actually feeds results into
GitHub Code Scanning — it needs if: always() so a failing scan (e.g.
dangerous skills found) doesn't skip the upload. use-llm: "true" installs the ai extra and enables LLM review; SKILLGUARD_SEMANTIC_MODEL
must match your provider — without a key in the environment the scan still runs
with the deterministic engines only.
Development
uv venv && source .venv/bin/activate
uv pip install -e ".[ai,dev]"
pytest -v # unit tests (no scanner binaries required)
pytest -m integration -v # requires real scanner binaries
Metadata
Release files for skillguard-core 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| skillguard_core-0.1.8.tar.gz | 130.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| skillguard_core-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 153.6 kB
Release files / skillguard_core-0.1.8.tar.gz
| Download URL | skillguard_core-0.1.8.tar.gz |
|---|---|
| Size | 130.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
07441a44239ea98be9154bdf889e5bbb3ffc96c0d507df37ceca6987d496aae3
|
|
BLAKE2b-256 checksum How to use checksums |
760d17c839dbb6bf1c5c426f8dbe5dcdc83c6e4eaf11a58522c626e14dad64cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / skillguard_core-0.1.8-py3-none-any.whl
| Download URL | skillguard_core-0.1.8-py3-none-any.whl |
|---|---|
| Size | 23.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f530339436b70acc0930130f94cd454d23a9db8ae8da99130dd2eaadf30ada1a
|
|
BLAKE2b-256 checksum How to use checksums |
7fe3bf662bc4781cbdbaa55faefa9afcd2e7d444aa24e7fe9408990d0ef57596
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|