From ee37b7054101c290647e810f87f64a0d2b2bba5b Mon Sep 17 00:00:00 2001 From: Ryan Eberhardt Date: Tue, 24 Mar 2026 21:01:45 -0700 Subject: [PATCH] Fix GitHub Actions workflow security issues (zizmor) - Fix template injection vulnerabilities by using environment variables instead of inline expressions in shell scripts (docker-stable, release) - Pin third-party actions to full SHA commits (docker-stable) - Add top-level permissions blocks with least-privilege scoping (docker-stable, e2e-test, version-check) - Add persist-credentials: false to all checkout steps - Add zizmor.yml configuration file - Fix missing newlines at end of files Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/docker-stable.yml | 25 ++++++++++++++++--------- .github/workflows/e2e-test.yml | 6 ++++++ .github/workflows/pr-preview.yml | 1 + .github/workflows/release.yml | 11 +++++++---- .github/workflows/version-check.yml | 6 ++++++ .github/zizmor.yml | 3 +++ 6 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 .github/zizmor.yml diff --git a/.github/workflows/docker-stable.yml b/.github/workflows/docker-stable.yml index 2a4c92d..3639ffc 100644 --- a/.github/workflows/docker-stable.yml +++ b/.github/workflows/docker-stable.yml @@ -6,39 +6,46 @@ on: description: 'Version to mark as stable (e.g., 1.2.3)' required: true +permissions: + contents: read + jobs: stable: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Check if version exists in PyPI id: version_check + env: + INPUT_VERSION: ${{ inputs.version }} run: | - if ! curl -s -f https://pypi.org/pypi/socketsecurity/${{ inputs.version }}/json > /dev/null; then - echo "Error: Version ${{ inputs.version }} not found on PyPI" + if ! curl -s -f "https://pypi.org/pypi/socketsecurity/${INPUT_VERSION}/json" > /dev/null; then + echo "Error: Version ${INPUT_VERSION} not found on PyPI" exit 1 fi - echo "Version ${{ inputs.version }} found on PyPI - proceeding with release" + echo "Version ${INPUT_VERSION} found on PyPI - proceeding with release" - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Login to Docker Hub with Organization Token - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build & Push Stable Docker - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: push: true platforms: linux/amd64,linux/arm64 tags: socketdev/cli:stable build-args: | CLI_VERSION=${{ inputs.version }} - \ No newline at end of file + diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index c5426fb..03584f6 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -6,6 +6,9 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + jobs: e2e-scan: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository @@ -14,6 +17,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 + persist-credentials: false - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: @@ -56,6 +60,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 + persist-credentials: false - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: @@ -96,6 +101,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 + persist-credentials: false - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index c14f190..1d7115a 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -15,6 +15,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 + persist-credentials: false - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: python-version: '3.13' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99372b6..5549b88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 + persist-credentials: false - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: python-version: '3.13' @@ -26,11 +27,13 @@ jobs: - name: Get Version id: version + env: + REF_NAME: ${{ github.ref_name }} run: | RAW_VERSION=$(hatch version) echo "VERSION=$RAW_VERSION" >> $GITHUB_ENV - if [ "v$RAW_VERSION" != "${{ github.ref_name }}" ]; then - echo "Error: Git tag (${{ github.ref_name }}) does not match hatch version (v$RAW_VERSION)" + if [ "v$RAW_VERSION" != "$REF_NAME" ]; then + echo "Error: Git tag ($REF_NAME) does not match hatch version (v$RAW_VERSION)" exit 1 fi @@ -52,7 +55,7 @@ jobs: env: VERSION: ${{ env.VERSION }} run: | - if curl -s -f "https://hub.docker.com/v2/repositories/socketdev/cli/tags/${{ env.VERSION }}" > /dev/null; then + if curl -s -f "https://hub.docker.com/v2/repositories/socketdev/cli/tags/${VERSION}" > /dev/null; then echo "Docker image socketdev/cli:${VERSION} already exists" echo "docker_exists=true" >> $GITHUB_OUTPUT else @@ -113,4 +116,4 @@ jobs: socketdev/cli:latest socketdev/cli:${{ env.VERSION }} build-args: | - CLI_VERSION=${{ env.VERSION }} \ No newline at end of file + CLI_VERSION=${{ env.VERSION }} diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml index 3276e73..5b9bda8 100644 --- a/.github/workflows/version-check.yml +++ b/.github/workflows/version-check.yml @@ -7,6 +7,11 @@ on: - 'setup.py' - 'pyproject.toml' +permissions: + contents: read + pull-requests: write + issues: write + jobs: check_version: runs-on: ubuntu-latest @@ -14,6 +19,7 @@ jobs: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: fetch-depth: 0 # Fetch all history for all branches + persist-credentials: false - name: Check version increment id: version_check diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000..39d1b18 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,3 @@ +rules: + secrets-outside-env: + disable: true