diff --git a/.github/actions/scorecard/action.yml b/.github/actions/scorecard/action.yml index 204f1ec..b9383e4 100644 --- a/.github/actions/scorecard/action.yml +++ b/.github/actions/scorecard/action.yml @@ -1,11 +1,21 @@ name: "OpenSSF Scorecard" description: | - Runs OpenSSF Scorecard checks, uploads SARIF to the GitHub Security tab, and publishes results to the OpenSSF database. - Required permissions on calling job: id-token: write, security-events: write, actions: read, contents: read + Runs OpenSSF Scorecard checks and uploads SARIF to the GitHub Security tab. + Required permissions on calling job: security-events: write, actions: read, contents: read + + WARNING — publish_results: this input is a known footgun. The OpenSSF scorecard webapp + verifies that the calling workflow directly invokes ossf/scorecard-action as a job step. + Composite action wrapping hides that call. Setting publish_results: true will ALWAYS fail + with HTTP 400 "workflow has no job that calls ossf/scorecard-action". The default is false + and should remain false. To publish to the OpenSSF public database, call + ossf/scorecard-action directly in your workflow instead of using this composite action. inputs: publish_results: - description: "Publish results to the public OpenSSF Scorecard database and generate the Scorecard badge. Set to false for private repositories." - default: "true" + description: | + WARNING: always fails with HTTP 400 when set to true. The scorecard webapp cannot see + through composite action wrapping to verify the ossf/scorecard-action call. Keep false + (default). To actually publish, call ossf/scorecard-action directly in your workflow. + default: "false" runs: using: "composite" steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ad4783..441671d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,8 +5,6 @@ name: CI on: push: branches: [main] - paths: - - '.github/**' pull_request: schedule: - cron: '0 6 * * 1' # weekly Monday 06:00 UTC — for scorecard @@ -53,12 +51,11 @@ jobs: scorecard: name: OpenSSF Scorecard runs-on: ubuntu-latest - if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' permissions: contents: read actions: read security-events: write - id-token: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/README.md b/README.md index 6c2d5b8..7ad77d3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ gh api repos/sparkgeo/github-actions/commits/main --jq '.sha' |---|---|---|---| | GitHub Actionlint | [`github-actionlint`](.github/actions/github-actionlint/action.yml) | Lints workflow and action YAML files using actionlint via reviewdog; posts annotations as GitHub Checks | None | | Zizmor | [`zizmor`](.github/actions/zizmor/action.yml) | Runs zizmor static security analysis against workflow and action YAML files; uploads findings as SARIF to the Security tab | None | -| OpenSSF Scorecard | [`scorecard`](.github/actions/scorecard/action.yml) | Runs OpenSSF Scorecard checks; uploads SARIF to the Security tab and publishes results to the OpenSSF database | `publish_results` (default: `true` — set to `false` for private repos) | +| OpenSSF Scorecard | [`scorecard`](.github/actions/scorecard/action.yml) | Runs OpenSSF Scorecard checks; uploads SARIF to the Security tab | `publish_results` (default: `false` — always fails with HTTP 400 if set to `true`; see action description) | | Dependency Review | [`dependency-review`](.github/actions/dependency-review/action.yml) | Blocks PRs introducing dependencies with known vulnerabilities or denied licenses; posts a summary comment | `fail-on-severity` (default: `high`), `deny-licenses` (default: `GPL-2.0,GPL-3.0,AGPL-3.0`), `comment-summary-in-pr` (default: `on-failure`) | | Storage Optimizer | [`storage-optimizer`](.github/actions/storage-optimizer/action.yml) | Frees disk space on GitHub-hosted runners by removing unused toolchains (JDK, .NET, Swift, Android SDK, etc.) and pruning Docker | None | | Terramate + OpenTofu Setup | [`terramate-opentofu-setup`](.github/actions/terramate-opentofu-setup/action.yml) | Installs Terramate and OpenTofu, validates generated files are up to date, initialises changed stacks, and lists changed stacks | `opentofu_version` (default: `1.10.0`), `terramate_version` (default: `0.14.7`) | @@ -62,7 +62,9 @@ jobs: ### OpenSSF Scorecard -Requires `id-token: write` for OIDC signing. Only runs on public repos with `publish_results: true`. +SARIF is always uploaded to the GitHub Security tab. Does not require `id-token: write` — `publish_results` defaults to `false` and no OIDC token is consumed. + +> **Note on `publish_results`:** Setting `publish_results: true` always fails with HTTP 400. The scorecard webapp verifies that the calling workflow directly invokes `ossf/scorecard-action` as a job step — composite action wrapping hides that call. Keep the default (`false`). To publish to the public OpenSSF database, call `ossf/scorecard-action` directly in your workflow. ```yaml jobs: @@ -72,12 +74,12 @@ jobs: contents: read actions: read security-events: write - id-token: write steps: - uses: actions/checkout@ with: persist-credentials: false - uses: sparkgeo/github-actions/.github/actions/scorecard@ + # publish_results defaults to false — do not set to true (always fails with HTTP 400) ``` ### Dependency Review diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..a24ebbd --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,45 @@ +# Security Policy + +## Reporting a Vulnerability + +**Do not open a public GitHub issue for security vulnerabilities.** + +Report vulnerabilities via the [GitHub Security Advisory](../../security/advisories/new) process: + +1. Go to the **Security** tab of this repository. +2. Click **Report a vulnerability**. +3. Fill in the advisory form with a description, affected versions, and reproduction steps. + +Alternatively, email **info@sparkgeo.com** with the subject line `[SECURITY] sparkgeo/github-actions`. + +## Disclosure Timeline + +| Phase | Target | +|---|---| +| Acknowledgement | Within 2 business days of receipt | +| Initial assessment | Within 5 business days | +| Fix or mitigation | Within 30 days for high/critical; 90 days for moderate/low | +| Public disclosure | After fix is released, or 90 days from report (whichever comes first) | + +We follow coordinated vulnerability disclosure. If we cannot ship a fix within 90 days, we will notify the reporter and agree on an extended timeline before any public disclosure. + +## Scope + +This repository contains reusable GitHub Actions composite actions. Vulnerabilities in scope include: + +- Supply chain risks in pinned action SHAs or version references +- Script injection via user-controlled context variables in workflow or action YAML +- Overly permissive `GITHUB_TOKEN` permissions that could be exploited +- Secrets or credentials inadvertently exposed in workflow logs or artifacts +- Logic errors in composite actions that could cause callers to grant unintended access + +Out of scope: vulnerabilities in third-party actions referenced by this repo (report those upstream). We will update our pinned SHA if a referenced action releases a security patch. + +## Supported Versions + +This repo does not use versioned releases. All consumers should pin to a specific commit SHA and update via Dependabot or Renovate (see `docs/approved-actions.md`). Only the current `main` branch is actively maintained. + +## Security Contacts + +- GitHub Security Advisory (preferred): https://github.com/sparkgeo/github-actions/security/advisories/new +- Email: info@sparkgeo.com