From cca07e7f048b65badaa36b62d18478b1f468125e Mon Sep 17 00:00:00 2001 From: Lucas Bedatty Date: Wed, 1 Apr 2026 12:10:43 -0300 Subject: [PATCH] fix(security): address CodeRabbit PR#195 review findings - scope id-token:write to build/docker jobs only (least privilege) - pin cosign-sign composite ref to v1.23.0 (remove mutable branch) - use inputs.ghcr_org fallback in build.yml cosign-refs step - scope certificate-identity-regexp in all cosign verify examples - add id-token:write to typescript-build.md basic example - qualify image ref in cosign-sign README single-image example - warn against secrets in docker_build_args descriptions - fix workflow_dispatch contradiction in cursor rules --- .cursor/rules/reusable-workflows.mdc | 2 +- .github/workflows/build.yml | 11 +++++++---- .github/workflows/go-release.yml | 7 +++++-- .github/workflows/pr-security-scan.yml | 2 +- .github/workflows/typescript-build.yml | 7 +++++-- docs/build-workflow.md | 2 +- docs/go-release-workflow.md | 2 +- docs/typescript-build.md | 3 ++- src/security/cosign-sign/README.md | 4 ++-- 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.cursor/rules/reusable-workflows.mdc b/.cursor/rules/reusable-workflows.mdc index 3a3081f..e68023b 100644 --- a/.cursor/rules/reusable-workflows.mdc +++ b/.cursor/rules/reusable-workflows.mdc @@ -127,8 +127,8 @@ runs-on: self-hosted Every reusable workflow must: - support `workflow_call` (for external callers) -- support `workflow_dispatch` (for manual testing) - expose explicit `inputs` — never rely on implicit context +- **must NOT** include a `workflow_dispatch` trigger — if manual/interactive dispatch is needed, create a separate self-workflow under `.github/workflows/self-*` - **always include a `dry_run` input** (`type: boolean`, `default: false`) so the workflow can be safely tested before applying real changes ```yaml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f1ab84..9363c9d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,7 +123,7 @@ on: type: boolean default: false docker_build_args: - description: 'Newline-separated Docker build arguments to pass to docker build (e.g., "APP_NAME=spi\nCOMPONENT_NAME=api"). Forwarded to docker/build-push-action build-args.' + description: 'Newline-separated Docker build arguments (e.g., "APP_NAME=spi\nCOMPONENT_NAME=api"). For sensitive values (tokens, keys, passwords), use BuildKit secrets instead — build arguments are visible in image history.' type: string required: false default: '' @@ -139,7 +139,6 @@ on: permissions: contents: read packages: write - id-token: write jobs: prepare: @@ -208,6 +207,10 @@ jobs: if: needs.prepare.outputs.has_builds == 'true' runs-on: ${{ inputs.runner_type }} name: Build ${{ matrix.app.name }} + permissions: + contents: read + packages: write + id-token: write strategy: max-parallel: 2 fail-fast: false @@ -320,7 +323,7 @@ jobs: ENABLE_GHCR: ${{ inputs.enable_ghcr }} DOCKERHUB_ORG: ${{ inputs.dockerhub_org }} APP_NAME: ${{ matrix.app.name }} - GHCR_ORG: ${{ steps.normalize.outputs.owner_lower }} + GHCR_ORG: ${{ inputs.ghcr_org || steps.normalize.outputs.owner_lower }} run: | REFS="" @@ -341,7 +344,7 @@ jobs: - name: Sign container images with cosign if: inputs.enable_cosign_sign - uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@feat/cosign-sign + uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@v1.23.0 with: image-refs: ${{ steps.cosign-refs.outputs.refs }} diff --git a/.github/workflows/go-release.yml b/.github/workflows/go-release.yml index acd1ec8..0b7f487 100644 --- a/.github/workflows/go-release.yml +++ b/.github/workflows/go-release.yml @@ -75,7 +75,6 @@ on: permissions: contents: write packages: write - id-token: write jobs: release: @@ -144,6 +143,10 @@ jobs: docker: name: Build and Push Docker Image runs-on: ${{ inputs.runner_type }} + permissions: + contents: read + packages: write + id-token: write needs: release if: inputs.enable_docker && startsWith(github.ref, 'refs/tags/v') @@ -194,7 +197,7 @@ jobs: - name: Sign container images with cosign if: inputs.enable_cosign_sign - uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@feat/cosign-sign + uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@v1.23.0 with: image-refs: ${{ steps.cosign-refs.outputs.refs }} diff --git a/.github/workflows/pr-security-scan.yml b/.github/workflows/pr-security-scan.yml index 3ead072..f6ed5c3 100644 --- a/.github/workflows/pr-security-scan.yml +++ b/.github/workflows/pr-security-scan.yml @@ -68,7 +68,7 @@ on: type: boolean default: true docker_build_args: - description: 'Newline-separated Docker build arguments to pass to docker build (e.g., "APP_NAME=spi\nCOMPONENT_NAME=api"). Forwarded to docker/build-push-action build-args.' + description: 'Newline-separated Docker build arguments (e.g., "APP_NAME=spi\nCOMPONENT_NAME=api"). For sensitive values (tokens, keys, passwords), use BuildKit secrets instead — build arguments are visible in image history.' type: string required: false default: '' diff --git a/.github/workflows/typescript-build.yml b/.github/workflows/typescript-build.yml index 91082e5..4f743a4 100644 --- a/.github/workflows/typescript-build.yml +++ b/.github/workflows/typescript-build.yml @@ -148,7 +148,6 @@ on: permissions: contents: read packages: write - id-token: write jobs: prepare: @@ -250,6 +249,10 @@ jobs: if: needs.prepare.outputs.has_builds == 'true' runs-on: ${{ inputs.runner_type }} name: Build ${{ matrix.app.name }} + permissions: + contents: read + packages: write + id-token: write strategy: max-parallel: 2 fail-fast: false @@ -333,7 +336,7 @@ jobs: - name: Sign container images with cosign if: inputs.enable_cosign_sign && !inputs.dry_run && steps.cosign-refs.outputs.refs != '' - uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@feat/cosign-sign + uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@v1.23.0 with: image-refs: ${{ steps.cosign-refs.outputs.refs }} diff --git a/docs/build-workflow.md b/docs/build-workflow.md index 3054f54..3991ce6 100644 --- a/docs/build-workflow.md +++ b/docs/build-workflow.md @@ -225,7 +225,7 @@ jobs: ```bash cosign verify \ - --certificate-identity-regexp=".*" \ + --certificate-identity-regexp="^https://github.com/LerianStudio/.*/.github/workflows/.*@refs/heads/.*$" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ docker.io/lerianstudio/my-app@sha256:abc123... ``` diff --git a/docs/go-release-workflow.md b/docs/go-release-workflow.md index 86412dd..e8b5a2d 100644 --- a/docs/go-release-workflow.md +++ b/docs/go-release-workflow.md @@ -204,7 +204,7 @@ jobs: ```bash cosign verify \ - --certificate-identity-regexp=".*" \ + --certificate-identity-regexp="^https://github.com/LerianStudio/.*/.github/workflows/.*@refs/heads/.*$" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ ghcr.io/myorg/my-app@sha256:abc123... ``` diff --git a/docs/typescript-build.md b/docs/typescript-build.md index 6623214..b8bdffd 100644 --- a/docs/typescript-build.md +++ b/docs/typescript-build.md @@ -37,6 +37,7 @@ on: permissions: contents: read packages: write + id-token: write # required for cosign keyless signing jobs: build: @@ -230,7 +231,7 @@ jobs: ```bash cosign verify \ - --certificate-identity-regexp=".*" \ + --certificate-identity-regexp="^https://github.com/LerianStudio/.*/.github/workflows/.*@refs/heads/.*$" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ ghcr.io/lerianstudio/my-app@sha256:abc123... ``` diff --git a/src/security/cosign-sign/README.md b/src/security/cosign-sign/README.md index 0151761..1bf4fbb 100644 --- a/src/security/cosign-sign/README.md +++ b/src/security/cosign-sign/README.md @@ -46,7 +46,7 @@ jobs: - name: Sign container image uses: LerianStudio/github-actions-shared-workflows/src/security/cosign-sign@v1.x.x with: - image-refs: myorg/myapp@${{ steps.build-push.outputs.digest }} + image-refs: docker.io/myorg/myapp@${{ steps.build-push.outputs.digest }} ``` ### Signing multiple registries @@ -64,7 +64,7 @@ jobs: ```bash cosign verify \ - --certificate-identity-regexp=".*" \ + --certificate-identity-regexp="^https://github.com/LerianStudio/.*/.github/workflows/.*@refs/heads/.*$" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ docker.io/myorg/myapp@sha256:abc123... ```