Skip to content
Cisco AI Defense logo
CiscoAI Security

GitHub Actions — Skill Scanner

GitHub Actions

Scan skills automatically on every push or pull request using the reusable GitHub Actions workflow. Results appear as inline annotations in PRs via GitHub Code Scanning.


Quick Start (No Keys Required)

Add this file to your repository at .github/workflows/scan-skills.yml:

name: Scan Skills

on:
  push:
    paths: [".cursor/skills/**"]
  pull_request:
    paths: [".cursor/skills/**"]

jobs:
  scan:
    uses: cisco-ai-defense/skill-scanner/.github/workflows/scan-skills.yml@main
    with:
      skill_path: .cursor/skills
    permissions:
      security-events: write
      contents: read

This will:

  1. Install cisco-ai-skill-scanner from PyPI on a fresh runner
  2. Run skill-scanner scan-all with SARIF output, recursive scanning, and cross-skill overlap detection
  3. Upload SARIF results to GitHub Code Scanning (findings appear as annotations on PRs)
  4. Fail the workflow if any findings at or above HIGH severity are detected

Reusable Workflow Inputs

InputTypeDefaultDescription
skill_pathstring(required)Path to skills directory or single skill
scan_modestringscan-allscan (single skill) or scan-all (directory)
formatstringsarifOutput format: summary, json, markdown, table, sarif, html
policystringbalancedPreset name or path to custom YAML
fail_on_severitystringhighFail if findings at/above this severity
python_versionstring3.12Python version for the runner
upload_sarifbooleantrueUpload SARIF to Code Scanning
use_llmbooleanfalseEnable LLM semantic analysis
llm_modelstring""LLM model name (e.g., gpt-4o)
use_behavioralbooleanfalseEnable behavioral dataflow analysis
lenientbooleanfalseTolerate malformed skills
extra_argsstring""Additional CLI flags passed verbatim

Secrets

All secrets are optional and only needed for advanced analysis.

SecretMaps ToRequired For
llm_api_keySKILL_SCANNER_LLM_API_KEYuse_llm: true
virustotal_api_keyVIRUSTOTAL_API_KEY--use-virustotal (via extra_args)

Configure secrets in Settings > Secrets and variables > Actions. They are never exposed in logs.


Configuration Tiers

Tier 1: Static Analysis (No Keys)

Zero-config static scanning with SARIF upload:

jobs:
  scan:
    uses: cisco-ai-defense/skill-scanner/.github/workflows/scan-skills.yml@main
    with:
      skill_path: .cursor/skills

Tier 2: Static + LLM (One Key)

Add LLM-powered semantic analysis:

jobs:
  scan:
    uses: cisco-ai-defense/skill-scanner/.github/workflows/scan-skills.yml@main
    with:
      skill_path: .cursor/skills
      use_llm: true
      llm_model: gpt-4o
    secrets:
      llm_api_key: ${{ secrets.SKILL_SCANNER_LLM_API_KEY }}

Tier 3: Full Stack (All Keys)

Enable every analyzer including VirusTotal and behavioral analysis:

jobs:
  scan:
    uses: cisco-ai-defense/skill-scanner/.github/workflows/scan-skills.yml@main
    with:
      skill_path: .cursor/skills
      use_llm: true
      use_behavioral: true
      policy: strict
    secrets:
      llm_api_key: ${{ secrets.SKILL_SCANNER_LLM_API_KEY }}
      virustotal_api_key: ${{ secrets.VIRUSTOTAL_API_KEY }}

Branch Protection

Block PRs with security findings from merging:

  1. Go to Settings > Branches > Branch protection rules
  2. Enable Require status checks to pass before merging
  3. Search for and select the Skill Scanner check
  4. Save changes

PRs that touch skill files must pass the security scan before they can be merged.


Pre-commit Hook

Scan skills before every commit using the pre-commit framework:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/cisco-ai-defense/skill-scanner
    rev: v1.0.0
    hooks:
      - id: skill-scanner

Or install the built-in hook directly:

skill-scanner-pre-commit install

The hook scans staged skill directories and blocks commits when findings exceed the configured severity threshold. Use --all to scan everything.


Self-Hosted Workflow

If you prefer not to use the reusable workflow, copy this standalone workflow:

name: Scan Skills

on:
  push:
    paths: [".cursor/skills/**"]
  pull_request:
    paths: [".cursor/skills/**"]

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - run: pip install cisco-ai-skill-scanner

      - name: Scan skills
        run: |
          skill-scanner scan-all .cursor/skills \
            --format sarif \
            --output results.sarif \
            --recursive \
            --check-overlap \
            --fail-on-severity high

      - name: Upload SARIF
        if: always()
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: results.sarif

Custom Policy in CI

Commit a custom policy to the repository and reference it:

with:
  skill_path: .cursor/skills
  policy: .github/scan-policy.yaml

Or in the self-hosted workflow:

skill-scanner scan-all .cursor/skills \
  --policy .github/scan-policy.yaml \
  --format sarif \
  --output results.sarif \
  --fail-on-severity high