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
6 changes: 5 additions & 1 deletion .github/workflows/boj-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ jobs:
trigger-boj:
runs-on: ubuntu-latest
timeout-minutes: 15
if: ${{ vars.BOJ_SERVER_URL != '' || secrets.BOJ_SERVER_URL != '' }}
# No job-level enablement gate: the `secrets` context is not available in
# `if:` (referencing it invalidates the whole workflow), and gating on
# `vars` alone would silently drop a secret-only configuration. The
# "Trigger BoJ Server" step shell-guards on an empty BOJ_URL and exits 0,
# so an unconfigured repo is a fast no-op regardless of secret-or-var.
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down
35 changes: 22 additions & 13 deletions .github/workflows/scorecard-enforcer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ permissions:
contents: read

jobs:
# Scorecard publish job — must be isolated from run steps per OpenSSF guidance.
scorecard-publish:
# Publish job. The OSSF attestation flow requires that a job invoking
# ossf/scorecard-action with publish_results: true contain ONLY `uses:`
# steps (no `run:`). A `run:` step in this job makes the OSSF publish
# endpoint reject the upload with HTTP 400 ("scorecard job must only have
# steps with `uses`"), failing the whole workflow. Score enforcement is
# therefore split into the separate unprivileged `score-gate` job below.
scorecard:
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 15
permissions:
security-events: write
id-token: write # For OIDC
contents: read
actions: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand All @@ -47,29 +50,35 @@ jobs:
with:
sarif_file: results.sarif

# Score enforcement job — separate from publish to satisfy scorecard_publish_with_run_step rule.
scorecard-enforce:
# Unprivileged enforcement gate. Re-derives the score read-only (no
# publish, no id-token), so it may legally contain a `run:` step.
# NOTE: uses JSON output deliberately. The SARIF format does NOT carry the
# aggregate score at .runs[0].tool.driver.properties.score (it is absent
# there, so a SARIF-based gate reads the `// 0` fallback and ALWAYS fails
# the < MIN_SCORE check); the JSON format exposes the aggregate at the
# top-level `.score`. publish_results is false here and does not affect the
# computed score, so enforcement behaviour is unchanged.
score-gate:
runs-on: ubuntu-latest
timeout-minutes: 15
needs: scorecard-publish
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run Scorecard (score only, no publish)
- name: Run Scorecard (analysis only)
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
results_file: results.json
results_format: json
publish_results: false

- 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")
# JSON output carries the aggregate score at the top-level `.score`.
SCORE=$(jq -r '.score // 0' results.json 2>/dev/null || echo "0")

echo "OpenSSF Scorecard Score: $SCORE"

Expand Down
Loading