Security Scan #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Scan | |
| on: | |
| pull_request: | |
| paths: | |
| - 'skills/**' | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'skills/**' | |
| schedule: | |
| # Run daily security scan at 06:00 UTC | |
| - cron: '0 6 * * *' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| security-scan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| pip install pyyaml jsonschema | |
| - name: Run security scanner | |
| id: scan | |
| run: | | |
| python scripts/security_scanner.py skills/ --output security-report.json | |
| continue-on-error: true | |
| - name: Upload security report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: security-report | |
| path: security-report.json | |
| - name: Check results | |
| run: | | |
| if [ -f security-report.json ]; then | |
| FAILED=$(jq -r '.failed' security-report.json) | |
| PASSED=$(jq -r '.passed' security-report.json) | |
| TOTAL=$(jq -r '.total' security-report.json) | |
| echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- Total skills: $TOTAL" >> $GITHUB_STEP_SUMMARY | |
| echo "- ✓ Passed: $PASSED" >> $GITHUB_STEP_SUMMARY | |
| echo "- ✗ Failed: $FAILED" >> $GITHUB_STEP_SUMMARY | |
| if [ "$FAILED" -gt "0" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Failed Skills:" >> $GITHUB_STEP_SUMMARY | |
| jq -r '.skills[] | select(.safe == false) | "- `\(.path)`"' security-report.json >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| fi | |
| - name: Comment on PR | |
| if: github.event_name == 'pull_request' && always() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| if (!fs.existsSync('security-report.json')) return; | |
| const report = JSON.parse(fs.readFileSync('security-report.json', 'utf8')); | |
| let comment = '## 🔒 Security Scan Results\n\n'; | |
| comment += `- **Total skills**: ${report.total}\n`; | |
| comment += `- ✅ **Passed**: ${report.passed}\n`; | |
| comment += `- ❌ **Failed**: ${report.failed}\n\n`; | |
| if (report.failed > 0) { | |
| comment += '### ⚠️ Issues Found:\n\n'; | |
| for (const skill of report.skills) { | |
| if (!skill.safe) { | |
| comment += `#### \`${skill.path}\`\n`; | |
| for (const issue of skill.issues) { | |
| if (issue.severity === 'error') { | |
| comment += `- ❌ **${issue.type}**: ${issue.message}\n`; | |
| } else { | |
| comment += `- ⚠️ ${issue.type}: ${issue.message}\n`; | |
| } | |
| } | |
| comment += '\n'; | |
| } | |
| } | |
| } else { | |
| comment += '✅ All skills passed security validation!\n'; | |
| } | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: comment | |
| }); | |
| codeql-analysis: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| security-events: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: python, javascript | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v3 | |
| dependency-scan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy security scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' |