Skip to content
Merged
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
22 changes: 22 additions & 0 deletions .github/actions/repo-security-checks/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-License-Identifier: MPL-2.0
# Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
name: Repository Security Checks
description: Assert SECURITY.md exists and warn on unpinned actions in workflows.
runs:
using: composite
steps:
- name: Check SECURITY.md exists
shell: bash
run: |
if [ ! -f "SECURITY.md" ]; then
echo "::error::SECURITY.md is required"
exit 1
fi
- name: Check for pinned dependencies
shell: bash
run: |
unpinned=$(grep -r "uses:.*@v[0-9]" .github/workflows/*.yml 2>/dev/null | grep -v "#" | head -5 || true)
if [ -n "$unpinned" ]; then
echo "::warning::Found unpinned actions:"
echo "$unpinned"
fi
26 changes: 26 additions & 0 deletions .github/actions/scorecard-gate/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# SPDX-License-Identifier: MPL-2.0
# Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
name: Scorecard Score Gate
description: Fail when the OpenSSF Scorecard score is below the minimum.
inputs:
sarif:
description: Path to the Scorecard SARIF results file.
required: false
default: results.sarif
min-score:
description: Minimum acceptable score (0-10).
required: false
default: "5"
runs:
using: composite
steps:
- name: Check minimum score
shell: bash
run: |
SCORE=$(jq -r '.runs[0].tool.driver.properties.score // 0' "${{ inputs.sarif }}" 2>/dev/null || echo "0")
echo "OpenSSF Scorecard Score: $SCORE"
MIN_SCORE="${{ inputs.min-score }}"
if [ "$(echo "$SCORE < $MIN_SCORE" | bc -l)" = "1" ]; then
echo "::error::Scorecard score $SCORE is below minimum $MIN_SCORE"
exit 1
fi
45 changes: 14 additions & 31 deletions .github/workflows/scorecard-enforcer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,50 +43,33 @@ jobs:
name: scorecard-sarif
path: results.sarif
retention-days: 1
# The score gate runs in a separate job so the publish job (which holds the
# OIDC id-token) contains no custom run steps.
# The score gate runs the check via a local composite action so this
# scorecard-publishing workflow file contains no run: steps (the publish job
# holds the OIDC id-token; run logic lives in .github/actions/*).
score-gate:
needs: scorecard
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Download results artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: scorecard-sarif
- name: Check minimum score
run: |
# Parse score from results
SCORE=$(jq -r '.runs[0].tool.driver.properties.score // 0' results.sarif 2>/dev/null || echo "0")

echo "OpenSSF Scorecard Score: $SCORE"

# Minimum acceptable score (0-10 scale)
MIN_SCORE=5

if [ "$(echo "$SCORE < $MIN_SCORE" | bc -l)" = "1" ]; then
echo "::error::Scorecard score $SCORE is below minimum $MIN_SCORE"
exit 1
fi
# Check specific high-priority items
- name: Gate on minimum score
uses: ./.github/actions/scorecard-gate
with:
sarif: results.sarif
min-score: "5"
# Check specific high-priority items (run logic in a local composite action).
check-critical:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check SECURITY.md exists
run: |
if [ ! -f "SECURITY.md" ]; then
echo "::error::SECURITY.md is required"
exit 1
fi
- name: Check for pinned dependencies
run: |
# Check workflows for unpinned actions
unpinned=$(grep -r "uses:.*@v[0-9]" .github/workflows/*.yml 2>/dev/null | grep -v "#" | head -5 || true)
if [ -n "$unpinned" ]; then
echo "::warning::Found unpinned actions:"
echo "$unpinned"
fi
- name: Repository security checks
uses: ./.github/actions/repo-security-checks
Loading