release: v0.10.7 — Publishes the container image for the v0.10.6 fixes #40
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: Code Scan | |
| # Read-only security scanners that complement CodeQL. Each tool's findings | |
| # are uploaded as SARIF into the GitHub Security tab (code scanning), so they | |
| # sit alongside CodeQL and are reviewed together as a release gate. The SARIF | |
| # scanners (zizmor / semgrep / osv-scanner) report into the Security tab | |
| # rather than blocking a PR on a pre-existing finding; gitleaks is a hard gate | |
| # (test fixtures + in-tree public keys allowlisted) and actionlint reports | |
| # until its baseline is clean. | |
| # | |
| # All action uses are SHA-pinned (with a trailing version comment), matching | |
| # the rest of the repo's workflows. | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| # Workflow-level is read-only; only the SARIF-uploading jobs elevate. | |
| permissions: | |
| contents: read | |
| jobs: | |
| # ── actionlint: GitHub Actions workflow correctness (gate) ────────── | |
| actionlint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Run actionlint | |
| # Report-only on introduction so a pre-existing finding in another | |
| # workflow doesn't block PRs; flip to a hard gate once the baseline | |
| # is clean. | |
| # | |
| # The actionlint image is digest-pinned (not :latest) so a tag- | |
| # republish or registry compromise cannot swap the linter bytes | |
| # and emit a fake-clean result that masks a genuine workflow defect. | |
| # Refresh the digest on the same cadence as the other action pins. | |
| run: docker run --rm -v "${PWD}:/repo" -w /repo rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 -color || true # v1.7.12 | |
| # ── zizmor: GitHub Actions security audit (SARIF → Security tab) ──── | |
| zizmor: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| security-events: write # upload SARIF (code scanning) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.x' | |
| - name: Install zizmor | |
| # Version-pinned (not floating latest) so a compromised newer release | |
| # can't silently enter this security-events:write job; bump deliberately. | |
| run: pipx install zizmor==1.26.1 | |
| - name: Run zizmor | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Scope to first-party workflows. Passing `.` also descends into | |
| # vendored dependencies' own `.github/workflows/` (e.g. vendor/blamejs), | |
| # whose pipelines never run in this repo, surfacing findings about | |
| # third-party CI we don't control. Mirrors the semgrep job's vendor | |
| # exclusion — both keep the scan to code that executes here. | |
| run: zizmor --format sarif .github/workflows/ > zizmor.sarif || true | |
| - name: Upload SARIF | |
| if: ${{ always() && hashFiles('zizmor.sarif') != '' }} | |
| continue-on-error: true | |
| uses: github/codeql-action/upload-sarif@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 | |
| with: | |
| sarif_file: zizmor.sarif | |
| category: zizmor | |
| # ── Semgrep: SAST + Actions/secret rules (SARIF → Security tab) ───── | |
| semgrep: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| security-events: write # upload SARIF (code scanning) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.x' | |
| - name: Install Semgrep | |
| # Version-pinned (not floating latest) so a compromised newer release | |
| # can't silently enter this security-events:write job; bump deliberately. | |
| run: pipx install semgrep==1.168.0 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep scan \ | |
| --config p/default \ | |
| --config p/github-actions \ | |
| --config p/secrets \ | |
| --sarif --output semgrep.sarif \ | |
| --exclude vendor --exclude tests --exclude build || true | |
| - name: Upload SARIF | |
| if: ${{ always() && hashFiles('semgrep.sarif') != '' }} | |
| continue-on-error: true | |
| uses: github/codeql-action/upload-sarif@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 | |
| with: | |
| sarif_file: semgrep.sarif | |
| category: semgrep | |
| # ── OSV-Scanner: known CVEs across the vendored surface (SARIF) ───── | |
| # The vendored deps have no lockfile, so build the CycloneDX SBOM (the same | |
| # one shipped on each release) and scan that — every leaf bundle (blamejs + | |
| # noble-*) carries a purl/CPE for advisory mapping. | |
| osv-scanner: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| security-events: write # upload SARIF (code scanning) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '>=24.18.0' | |
| - name: Build CycloneDX SBOM | |
| run: node scripts/build-sbom.js --out build | |
| - name: Install OSV-Scanner | |
| id: osv_install | |
| env: | |
| # Pinned release + committed SHA-256 of osv-scanner_linux_amd64. | |
| # Bump both together when moving to a newer osv-scanner; the SUMS | |
| # file lives at the release's osv-scanner_SHA256SUMS asset. | |
| OSV_VERSION: v2.4.0 | |
| OSV_SHA256: 15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0 | |
| run: | | |
| # This job holds security-events:write, so a scanner binary pulled | |
| # from the mutable releases/latest path and run unverified could | |
| # execute attacker bytes and suppress the very code-scanning findings | |
| # this gate exists to surface. Pin to a specific release tag and | |
| # verify the asset's SHA-256 before chmod+exec — matching the SHA-pin | |
| # posture of every other executable input in this repo's CI. | |
| # | |
| # A network/download failure is an availability problem: warn + skip | |
| # the scan (SARIF is report-only). A checksum MISMATCH is an integrity | |
| # problem (tag-republish / asset swap): fail loudly rather than run or | |
| # silently skip, so a swapped binary can never emit a fake-clean SARIF. | |
| if ! curl -sSfL "https://github.com/google/osv-scanner/releases/download/${OSV_VERSION}/osv-scanner_linux_amd64" -o "${RUNNER_TEMP}/osv-scanner"; then | |
| echo "::warning::osv-scanner download failed; skipping scan" | |
| echo "ok=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! echo "${OSV_SHA256} ${RUNNER_TEMP}/osv-scanner" | sha256sum -c -; then | |
| echo "::error::osv-scanner ${OSV_VERSION} checksum mismatch; refusing to execute" | |
| exit 1 | |
| fi | |
| chmod +x "${RUNNER_TEMP}/osv-scanner" | |
| echo "ok=true" >> "$GITHUB_OUTPUT" | |
| - name: Scan SBOM | |
| if: ${{ steps.osv_install.outputs.ok == 'true' }} | |
| run: | | |
| SBOM=$(ls build/*.cdx.json | head -1) | |
| echo "Scanning ${SBOM}" | |
| "${RUNNER_TEMP}/osv-scanner" scan --format sarif --output osv.sarif --sbom "${SBOM}" || true | |
| - name: Upload SARIF | |
| if: ${{ always() && hashFiles('osv.sarif') != '' }} | |
| continue-on-error: true | |
| uses: github/codeql-action/upload-sarif@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 | |
| with: | |
| sarif_file: osv.sarif | |
| category: osv-scanner | |
| # ── Gitleaks: committed-secret scan (gate; tests/ allowlisted) ───── | |
| gitleaks: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 # full history so a secret added then removed is still caught | |
| - name: Run Gitleaks | |
| uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_CONFIG: .gitleaks.toml |