From 4fc6c10590f309f0bfcebb760899a30c0a3cc5a4 Mon Sep 17 00:00:00 2001 From: hubertlim Date: Fri, 23 May 2025 15:42:00 +0200 Subject: [PATCH] chore(security): pin GitHub Actions to commit SHAs and harden permissions Address OpenSSF Scorecard findings: - Pin all GitHub Actions to commit SHAs with version tag comments (resolves 41 PinnedDependencies alerts) - Move security-events:write permission from workflow-level to job-level in codeql.yml (resolves TokenPermissions alert) - Add explicit contents:read on all jobs Dependabot will continue to update SHAs while preserving the version tag comments for human readability. Also: tighten dependabot docker config to only accept patch-level bumps because language minor versions (e.g. python 3.12 -> 3.14) can lack prebuilt wheels and break the build. --- .github/dependabot.yml | 8 +++++-- .github/workflows/ci.yml | 32 ++++++++++++++-------------- .github/workflows/codeql.yml | 13 ++++++----- .github/workflows/infra-validate.yml | 10 ++++----- .github/workflows/scorecard.yml | 7 +++--- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3dcec36..da9401e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -91,11 +91,15 @@ updates: patterns: - "*" update-types: - - "minor" - "patch" ignore: + # Block all major and minor bumps. Language and base-image minor + # versions can introduce wheel incompatibilities (e.g. python 3.14 + # lacks prebuilt wheels for pydantic-core). Patch updates are safe. - dependency-name: "*" - update-types: ["version-update:semver-major"] + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" # --------------------------------------------------------------------------- # Terraform diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00db348..dc25a3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,15 +23,15 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.12" - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 with: node-version: "20" cache: "npm" @@ -60,15 +60,15 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.12" - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 with: node-version: "20" cache: "npm" @@ -105,10 +105,10 @@ jobs: contents: read security-events: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.12" @@ -124,7 +124,7 @@ jobs: continue-on-error: true - name: Run Trivy filesystem scan - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 with: scan-type: "fs" scan-ref: "." @@ -133,7 +133,7 @@ jobs: severity: "CRITICAL,HIGH" - name: Upload Trivy results to GitHub Security - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@dc73d59c2d7bd4f8194098a91219eeee6d8a1719 # v4.32.7 if: always() && hashFiles('trivy-results.sarif') != '' with: sarif_file: "trivy-results.sarif" @@ -149,21 +149,21 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.4.0 - name: Log in to Container Registry if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.0.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build API image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ./apps/api target: production @@ -175,7 +175,7 @@ jobs: cache-to: type=gha,mode=max - name: Build Web image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 with: context: ./apps/web target: production @@ -188,7 +188,7 @@ jobs: - name: Scan API image with Trivy if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 with: image-ref: "${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/api:${{ github.sha }}" format: "table" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2dd30b6..f4ccead 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -10,29 +10,32 @@ on: permissions: contents: read - security-events: write jobs: analyze: name: Analyze runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read strategy: fail-fast: false matrix: language: ["python", "javascript-typescript"] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@dc73d59c2d7bd4f8194098a91219eeee6d8a1719 # v4.32.7 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v4 + uses: github/codeql-action/autobuild@dc73d59c2d7bd4f8194098a91219eeee6d8a1719 # v4.32.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@dc73d59c2d7bd4f8194098a91219eeee6d8a1719 # v4.32.7 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/infra-validate.yml b/.github/workflows/infra-validate.yml index 144a129..8a82b94 100644 --- a/.github/workflows/infra-validate.yml +++ b/.github/workflows/infra-validate.yml @@ -25,10 +25,10 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up Terraform - uses: hashicorp/setup-terraform@v3 + uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 with: terraform_version: 1.9.0 terraform_wrapper: false @@ -54,10 +54,10 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Set up TFLint - uses: terraform-linters/setup-tflint@v4 + uses: terraform-linters/setup-tflint@6e87008f9dd1fe3e34e66aca6c97b4a69f72a7f4 # v4.0.0 with: tflint_version: latest @@ -79,7 +79,7 @@ jobs: matrix: overlay: [staging, production] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 - name: Install kustomize run: | diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 932eeef..0a04cb1 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -15,19 +15,20 @@ jobs: permissions: security-events: write id-token: write + contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 with: persist-credentials: false - name: Run OpenSSF Scorecard - uses: ossf/scorecard-action@v2.4.3 + uses: ossf/scorecard-action@99c09fe975337306107572b4fdf4db224cf8e2f2 # v2.4.3 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload Scorecard results - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@dc73d59c2d7bd4f8194098a91219eeee6d8a1719 # v4.32.7 with: sarif_file: results.sarif