diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..53b4a22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Report a bug or incorrect scan result +title: "bug: " +labels: ["bug"] +assignees: [] +--- + +## Description + + + +## Steps to reproduce + +```bash +skillspector scan [options] +``` + +## Expected behaviour + + + +## Actual behaviour + + + +
+Output + +``` +paste output here +``` + +
+ +## Environment + +- SkillSpector version: +- Python version: +- OS: +- LLM provider (if applicable): diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..f237335 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest a new feature or improvement +title: "feat: " +labels: ["enhancement"] +assignees: [] +--- + +## Summary + + + +## Motivation + + + +## Proposed solution + + + +## Alternatives considered + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f3bb6a5 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,27 @@ +## Summary + + + +Closes # + +## Changes + + + +- +- + +## Testing + + + +- [ ] `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`) diff --git a/.github/workflows/skillspector.yml b/.github/workflows/skillspector.yml new file mode 100644 index 0000000..650f9dc --- /dev/null +++ b/.github/workflows/skillspector.yml @@ -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 diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml new file mode 100644 index 0000000..068f5c3 --- /dev/null +++ b/.pre-commit-hooks.yaml @@ -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: [] diff --git a/README.md b/README.md index cca0724..46d1d12 100644 --- a/README.md +++ b/README.md @@ -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