scorecard-enforcer.yml
1 # SPDX-License-Identifier: AGPL-3.0-or-later 2 # Prevention workflow - runs OpenSSF Scorecard and fails on low scores 3 name: OpenSSF Scorecard Enforcer 4 5 on: 6 push: 7 branches: [main] 8 schedule: 9 - cron: '0 6 * * 1' # Weekly on Monday 10 workflow_dispatch: 11 12 permissions: read-all 13 14 jobs: 15 scorecard: 16 runs-on: ubuntu-latest 17 permissions: 18 security-events: write 19 id-token: write # For OIDC 20 steps: 21 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 22 with: 23 persist-credentials: false 24 25 - name: Run Scorecard 26 uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 27 with: 28 results_file: results.sarif 29 results_format: sarif 30 publish_results: true 31 32 - name: Upload SARIF 33 uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3 34 with: 35 sarif_file: results.sarif 36 37 - name: Check minimum score 38 run: | 39 # Parse score from results 40 SCORE=$(jq -r '.runs[0].tool.driver.properties.score // 0' results.sarif 2>/dev/null || echo "0") 41 42 echo "OpenSSF Scorecard Score: $SCORE" 43 44 # Minimum acceptable score (0-10 scale) 45 MIN_SCORE=5 46 47 if [ "$(echo "$SCORE < $MIN_SCORE" | bc -l)" = "1" ]; then 48 echo "::error::Scorecard score $SCORE is below minimum $MIN_SCORE" 49 exit 1 50 fi 51 52 # Check specific high-priority items 53 check-critical: 54 runs-on: ubuntu-latest 55 steps: 56 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 57 58 - name: Check SECURITY.md exists 59 run: | 60 if [ ! -f "SECURITY.md" ]; then 61 echo "::error::SECURITY.md is required" 62 exit 1 63 fi 64 65 - name: Check for pinned dependencies 66 run: | 67 # Check workflows for unpinned actions 68 unpinned=$(grep -r "uses:.*@v[0-9]" .github/workflows/*.yml 2>/dev/null | grep -v "#" | head -5 || true) 69 if [ -n "$unpinned" ]; then 70 echo "::warning::Found unpinned actions:" 71 echo "$unpinned" 72 fi