Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: Bug report
about: Report a bug or incorrect scan result
title: "bug: "
labels: ["bug"]
assignees: []
---

## Description

<!-- A clear and concise description of what the bug is. -->

## Steps to reproduce

```bash
skillspector scan <input> [options]
```

## Expected behaviour

<!-- What did you expect to happen? -->

## Actual behaviour

<!-- What actually happened? Paste relevant output below. -->

<details>
<summary>Output</summary>

```
paste output here
```

</details>

## Environment

- SkillSpector version: <!-- run `skillspector --version` -->
- Python version: <!-- run `python --version` -->
- OS:
- LLM provider (if applicable):
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Feature request
about: Suggest a new feature or improvement
title: "feat: "
labels: ["enhancement"]
assignees: []
---

## Summary

<!-- One sentence: what should SkillSpector do that it can't do today? -->

## Motivation

<!-- Why is this valuable? What problem does it solve? -->

## Proposed solution

<!-- Describe your proposed approach. Code sketches welcome but not required. -->

## Alternatives considered

<!-- Any alternative approaches you thought about? -->
27 changes: 27 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Summary

<!-- One paragraph: what does this PR do and why? -->

Closes #<!-- issue number -->

## Changes

<!-- Bullet list of what changed -->

-
-

## Testing

<!-- How did you verify your changes? -->

- [ ] `make test` passes
- [ ] `make lint` passes
- [ ] `make format-check` passes

## Checklist

- [ ] SPDX license header added to every new `.py` file
- [ ] Unit tests added / updated for new behaviour
- [ ] Documentation updated (README, docstrings) if user-facing
- [ ] Commits are signed off (`git commit -s`)
87 changes: 87 additions & 0 deletions .github/workflows/skillspector.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# SkillSpector CI — scans for security vulnerabilities in AI agent skills.
#
# This workflow runs on every pull request and push to main. It uses the
# SARIF output format so findings appear inline on the GitHub PR diff via
# GitHub Code Scanning (Advanced Security).
#
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: SkillSpector Security Scan

on:
push:
branches: [main]
pull_request:
branches: [main]
# Allow manual runs from the Actions tab
workflow_dispatch:

permissions:
# Required to upload SARIF results to GitHub Code Scanning
security-events: write
# Required to check out the repository
contents: read

jobs:
scan:
name: Scan skills for vulnerabilities
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install SkillSpector
run: pip install skillspector

# ------------------------------------------------------------------ #
# Static-only scan (no LLM required, works without any API key). #
# Scans the entire repository root as a single skill bundle. #
# ------------------------------------------------------------------ #
- name: Run SkillSpector (static analysis)
id: skillspector
# Continue even on non-zero exit (risk > 50) so we can upload SARIF
continue-on-error: true
run: |
skillspector scan . \
--no-llm \
--format sarif \
--output skillspector-results.sarif

# ------------------------------------------------------------------ #
# Optional: LLM-enriched scan. #
# Uncomment and set SKILLSPECTOR_PROVIDER + the matching API key #
# secret in your repository settings to enable semantic analysis. #
# ------------------------------------------------------------------ #
# - name: Run SkillSpector (with LLM analysis)
# continue-on-error: true
# env:
# SKILLSPECTOR_PROVIDER: anthropic
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# run: |
# skillspector scan . \
# --format sarif \
# --output skillspector-results.sarif

- name: Upload SARIF results to GitHub Code Scanning
# Always upload so findings appear even when the scan exits non-zero
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: skillspector-results.sarif
category: skillspector

# Fail the job if SkillSpector reported a high/critical risk score
- name: Check scan result
if: steps.skillspector.outcome == 'failure'
run: |
echo "::error::SkillSpector detected HIGH or CRITICAL risk (score > 50)."
echo "Review the Security tab for details, then fix or suppress findings."
exit 1
38 changes: 38 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# SkillSpector pre-commit hook definition.
#
# To use in your project, add the following to your .pre-commit-config.yaml:
#
# repos:
# - repo: https://github.com/NVIDIA/skillspector
# rev: v2.1.4 # pin to a release tag
# hooks:
# - id: skillspector
#
# The hook runs a static-only scan (--no-llm) so it works without any API key.
# For LLM-enriched results, override args in your local config:
#
# hooks:
# - id: skillspector
# args: [] # removes --no-llm, requires SKILLSPECTOR_PROVIDER + credentials

- id: skillspector
name: SkillSpector — AI skill security scan
description: >
Scans AI agent skill files for vulnerabilities, malicious patterns, and
security risks before they are committed. Exits non-zero when the risk
score exceeds 50 (HIGH or CRITICAL). Uses static analysis only by default
(no LLM API key required).
language: python
entry: skillspector scan
args: [--no-llm]
# Run once on the repo root, not per-file, so the graph can walk all files.
pass_filenames: false
# Trigger when any of these file types change inside a skill directory.
types_or: [markdown, python, yaml, json, shell, text]
# Always run so the scanner sees the full skill directory state.
always_run: false
# Requires skillspector to be installed in the pre-commit env.
additional_dependencies: []
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,78 @@ Options:
--help Show this message and exit
```

## CI/CD Integration

### GitHub Actions

The repository ships a ready-to-use workflow at
[`.github/workflows/skillspector.yml`](.github/workflows/skillspector.yml)
that you can copy into your own repository. It runs a static scan on every
pull request and uploads the results to **GitHub Code Scanning** so findings
appear inline on the PR diff.

```yaml
# .github/workflows/skillspector.yml (copy this into your repo)
name: SkillSpector Security Scan
on: [push, pull_request]
permissions:
security-events: write
contents: read
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "3.12"}
- run: pip install skillspector
- name: Scan skills
continue-on-error: true
run: skillspector scan . --no-llm --format sarif --output results.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: {sarif_file: results.sarif}
```

> **Note**: GitHub Code Scanning (which displays SARIF findings) requires
> GitHub Advanced Security, available on public repositories and on
> GitHub Enterprise.

### pre-commit Hook

SkillSpector ships a [pre-commit](https://pre-commit.com) hook so you can
scan skills automatically before every commit — no API key required.

Add the following to your project's `.pre-commit-config.yaml`:

```yaml
repos:
- repo: https://github.com/NVIDIA/skillspector
rev: v2.1.4 # pin to a release tag
hooks:
- id: skillspector
```

Then install the hooks once:

```bash
pip install pre-commit
pre-commit install
```

From that point on, every `git commit` that touches Markdown, Python, YAML,
or shell files will trigger a static scan. The commit is blocked if the
risk score exceeds 50.

To enable LLM-enriched analysis in the hook, override `args` and set your
provider credentials in the shell environment:

```yaml
hooks:
- id: skillspector
args: [] # removes --no-llm
```

## Development

### Setup
Expand Down