From 165575dcc4dc2c2b73bec13869228bcf9b0b8709 Mon Sep 17 00:00:00 2001 From: Ryan Hill Date: Thu, 20 Aug 2026 16:45:19 -0500 Subject: [PATCH 1/2] Add OpenSSF Scorecard workflow to publish a public security score Mirrors qBraid/qBraid#1343 so the two repositories are graded the same way. Runs weekly and on pushes to main, checks supply-chain practices such as branch protection, token permissions, dependency pinning and signed releases, uploads SARIF to code scanning, and publishes the aggregate score. publish_results: true is what makes the score publicly visible; it reports check results, not source. Expect a middling first score. Several checks will fail on things already known here, and that is the point of establishing a baseline. --- .github/workflows/scorecard.yml | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..40acfd3 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,46 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + schedule: + - cron: '31 5 * * 1' + push: + branches: [ main ] + workflow_dispatch: + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + security-events: write # upload SARIF to code scanning + id-token: write # publish results to the public Scorecard API + contents: read + actions: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@v2 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: Upload to code scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif From e5b76f7e91fa62b8e0c7dcd3a208ee4ed8936461 Mon Sep 17 00:00:00 2001 From: Ryan Hill Date: Mon, 24 Aug 2026 16:36:41 -0500 Subject: [PATCH 2/2] ci: pin scorecard actions to SHAs, drop default permissions to none Addresses the review on #94. `ossf/scorecard-action@v2` did not resolve: that repository publishes v2.3.3 through v2.4.4 and has no `v2` tag or branch, so the step could never have run. Pinning fixes it as a side effect. Every action is now pinned to a full commit SHA with its release in a comment. A tag is mutable and can be repointed at other code, which is what Scorecard's own Pinned-Dependencies check looks for. Each SHA was resolved from its upstream repository rather than copied from the review: the suggested codeql-action SHA was v3.37.7, superseded by v3.37.8 on 2026-08-21. Workflow default permissions drop from `read-all` to `{}`. Job-level permissions replace the workflow block rather than extending it, so `analysis` is unaffected, but a job added later now starts with nothing instead of repository-wide read. Added a concurrency group so overlapping runs from the four triggers cannot publish SARIF out of order, and a comment recording why `actions: read` is present -- upstream documents it for private repositories, and this repo is public, so it is a safeguard rather than a requirement. --- .github/workflows/scorecard.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 40acfd3..4299c70 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -8,7 +8,17 @@ on: branches: [ main ] workflow_dispatch: -permissions: read-all +# Four triggers can overlap, and Scorecard reports current repository state, so a +# superseded run has nothing to contribute. Cancelling keeps the published SARIF and the +# public API entry in trigger order. +concurrency: + group: scorecard + cancel-in-progress: true + +# Least privilege by default: `analysis` names everything it needs below, and a job added +# later gets nothing until it does the same. Job-level permissions replace this block +# rather than adding to it. +permissions: {} jobs: analysis: @@ -18,29 +28,34 @@ jobs: security-events: write # upload SARIF to code scanning id-token: write # publish results to the public Scorecard API contents: read + # Lets Scorecard read workflow definitions and run history. Documented by the + # upstream starter workflow as required for private repositories; this repo is + # public, so it is retained only as a safeguard should that ever change. actions: read + # Actions are pinned to full commit SHAs: a tag is mutable and can be repointed at + # other code, which is what Scorecard's own Pinned-Dependencies check looks for. steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@v2 + uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif retention-days: 5 - name: Upload to code scanning - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@42947a340483f03ba47bb1a039b2c519aab3df85 # v3.37.8 with: sarif_file: results.sarif