Files
wehub-resource-sync bb5c75ce05
Component Security Validation / Security Audit (push) Has been cancelled
Deploy to Cloudflare Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:58 +08:00

104 lines
3.2 KiB
YAML

name: Skill Security Scan
# Runs SkillSpector (NVIDIA, Apache-2.0) static analysis on skill components
# changed in a PR. Posts a report comment and blocks the PR if any changed
# skill scores HIGH/CRITICAL (risk score > 50).
on:
pull_request:
paths:
- 'cli-tool/components/skills/**'
- 'scripts/skillspector_scan.py'
- '.github/workflows/skill-security-scan.yml'
permissions:
contents: read
pull-requests: write
security-events: write
jobs:
skill-scan:
name: SkillSpector (changed skills)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # full history so git diff against the base ref works
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install SkillSpector
run: pip install "git+https://github.com/NVIDIA/skillspector.git@main"
- name: Run SkillSpector on changed skills
id: scan
continue-on-error: true
run: |
python scripts/skillspector_scan.py \
--changed \
--base-ref "origin/${{ github.base_ref }}" \
--fail-on-risk \
--threshold 50 \
--output-md skillspector-report.md \
--output-sarif skillspector.sarif
- name: Upload report artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: skillspector-report
path: |
skillspector-report.md
skillspector.sarif
retention-days: 30
- name: Upload SARIF to code scanning
if: always()
continue-on-error: true
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: skillspector.sarif
category: skillspector
- name: Comment PR with results
if: always()
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const reportPath = 'skillspector-report.md';
if (!fs.existsSync(reportPath)) {
console.log('No SkillSpector report found.');
return;
}
const body = fs.readFileSync(reportPath, 'utf8');
const marker = '<!-- skillspector-report:v1 -->';
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const existing = await github.paginate(
github.rest.issues.listComments,
{ owner, repo, issue_number, per_page: 100 }
);
const prev = existing.find(c => c.body && c.body.includes(marker));
if (prev) {
await github.rest.issues.updateComment({
owner, repo, comment_id: prev.id, body,
});
} else {
await github.rest.issues.createComment({
owner, repo, issue_number, body,
});
}
- name: Enforce gate
if: steps.scan.outputs.failed == 'true'
run: |
echo "::error::SkillSpector found HIGH/CRITICAL findings in changed skills (${{ steps.scan.outputs.high_critical_count }})."
exit 1