From fb51305a41488762ccd291b58dcbbaea4f784059 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Wed, 11 Dec 2024 17:33:21 -0800 Subject: [PATCH] Lint our GitHub Actions workflows with zizmor zizmor is a new tool to lint GitHub Actions workflows. For the most part our workflows are pretty low risk since we don't give it a bunch of credentials, but we can avoid issues in the future by locking them down now. Two overall issues needed to be fixed: * setting persist-credentials: false for actions/checkout, which we do everywhere except in the workflows that need to push. * Don't use template expansion when we can use a normal bash variable. While zizmor is written in Rust, it is also shipped as a prebuilt binary via PyPI, so we can set it as a poetry dependency and run it as part of our normal lint CI. Refs . --- .github/workflows/build.yml | 11 +++++++++++ .github/workflows/cargo-vet.yml | 4 +++- .github/workflows/ci.yml | 12 ++++++++++++ .github/workflows/nightlies.yml | 7 +++++++ .github/workflows/sdk.yml | 3 +++ .github/workflows/security.yml | 2 ++ .github/workflows/test.yml | 7 ++++++- Makefile | 6 +++++- poetry.lock | 27 +++++++++++++++++++++++++-- pyproject.toml | 1 + 10 files changed, 75 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f106d7857..5b7f61a57 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,8 +25,11 @@ jobs: - run: | apt-get update && apt-get install --yes git git-lfs sudo make - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: + persist-credentials: false repository: "freedomofpress/securedrop-builder" path: "securedrop-builder" lfs: true @@ -54,8 +57,11 @@ jobs: artifact_id: ${{ steps.upload.outputs.artifact-id }} steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: + persist-credentials: false repository: "freedomofpress/securedrop-builder" path: "securedrop-builder" lfs: true @@ -81,8 +87,11 @@ jobs: artifact_id: ${{ steps.upload.outputs.artifact-id }} steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: + persist-credentials: false repository: "freedomofpress/securedrop-builder" path: "securedrop-builder" lfs: true @@ -145,6 +154,8 @@ jobs: - build-debs steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/download-artifact@v4 with: pattern: "build-${{ matrix.debian_version }}" diff --git a/.github/workflows/cargo-vet.yml b/.github/workflows/cargo-vet.yml index 2f667039e..02accb42c 100644 --- a/.github/workflows/cargo-vet.yml +++ b/.github/workflows/cargo-vet.yml @@ -21,6 +21,8 @@ jobs: CARGO_VET_VERSION: 0.10.0 steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/cache@v4 id: cache-vet with: @@ -28,6 +30,6 @@ jobs: key: cargo-vet-${{ env.CARGO_VET_VERSION }} - name: Install the cargo-vet binary, if needed if: ${{ steps.cache-vet.outputs.cache-hit != 'true' }} - run: cargo install --version ${{ env.CARGO_VET_VERSION }} cargo-vet + run: cargo install --version $CARGO_VET_VERSION cargo-vet - name: Invoke cargo-vet run: cargo vet --locked diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 534ed44d2..e6e3e2c7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make apparmor - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Lint AppArmor profiles run: | make lint-apparmor @@ -40,6 +42,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make desktop-file-utils - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Lint .desktop files run: | make lint-desktop @@ -55,6 +59,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make file python3-poetry - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install dependencies run: | poetry install @@ -80,6 +86,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make gnupg python3-poetry - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install dependencies run: | poetry -C ${{ matrix.component }} install @@ -96,6 +104,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make python3-poetry - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Run safety run: | poetry install @@ -108,6 +118,8 @@ jobs: container: rust:1.81.0 steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Configure Qubes repository run: | cp scripts/qubes_42.sources /etc/apt/sources.list.d/ diff --git a/.github/workflows/nightlies.yml b/.github/workflows/nightlies.yml index d08c0f4a6..4c23e6919 100644 --- a/.github/workflows/nightlies.yml +++ b/.github/workflows/nightlies.yml @@ -27,8 +27,11 @@ jobs: artifact_id: ${{ steps.upload.outputs.artifact-id }} steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: + persist-credentials: false repository: "freedomofpress/securedrop-builder" path: "securedrop-builder" lfs: true @@ -58,12 +61,16 @@ jobs: pattern: "*${{ matrix.debian_version }}" - uses: actions/checkout@v4 with: + # We need to store credentials here + persist-credentials: true repository: "freedomofpress/securedrop-apt-test" path: "securedrop-apt-test" lfs: true token: ${{ secrets.PUSH_TOKEN }} - uses: actions/checkout@v4 with: + # We need to store credentials here + persist-credentials: true repository: "freedomofpress/build-logs" path: "build-logs" token: ${{ secrets.PUSH_TOKEN }} diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index a4b86061b..842609543 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -20,8 +20,11 @@ jobs: DOCKERIZE_VERSION: "v0.7.0" steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: + persist-credentials: false repository: "freedomofpress/securedrop" path: "securedrop-server" - uses: actions/setup-python@v5 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 520c4eba1..514280d6c 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -10,6 +10,8 @@ jobs: container: rust:1.81.0 steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Check Rust dependencies run: | cargo install cargo-audit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ea62f1e0c..f3ca99f94 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,6 @@ jobs: steps: - run: | apt-get update && apt-get install --yes git make gnupg sudo python3-poetry - - uses: actions/checkout@v4 - name: Setup user run: | # We want to run tests as a regular user, similar to Qubes VMs @@ -42,6 +41,8 @@ jobs: run: apt-get install --yes build-essential curl libssl-dev pkg-config if: ${{ matrix.component == 'proxy' }} - uses: actions/checkout@v4 + with: + persist-credentials: false # Install Rust, keep in sync with rust-toolchain.toml - uses: dtolnay/rust-toolchain@1.81.0 if: ${{ matrix.component == 'proxy' }} @@ -74,6 +75,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make gnupg sudo python3-poetry - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup user run: | # We want to run tests as a regular user, similar to Qubes VMs @@ -100,6 +103,8 @@ jobs: - run: | apt-get update && apt-get install --yes git make python3-poetry - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install dependencies run: | poetry -C client install diff --git a/Makefile b/Makefile index c7726ca26..2cc17e45d 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ lint-desktop: ## Lint .desktop files find . -name *.desktop -type f -not -path '*/\.git/*' | xargs desktop-file-validate .PHONY: lint -lint: check-ruff shellcheck ## Run linters and formatters +lint: check-ruff shellcheck zizmor ## Run linters and formatters .PHONY: fix fix: ## Fix lint and formatting issues @@ -54,6 +54,10 @@ safety: ## Run safety dependency checks on build dependencies shellcheck: ## Lint shell scripts @poetry run ./scripts/shellcheck.sh +.PHONY: zizmor +zizmor: ## Lint GitHub Actions workflows + @poetry run zizmor . + .PHONY: rust-lint rust-lint: ## Lint Rust code cargo fmt --check diff --git a/poetry.lock b/poetry.lock index a3a3323fa..a1b913dba 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "authlib" @@ -795,7 +795,30 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "zizmor" +version = "0.8.0" +description = "Static analysis for GitHub Actions" +optional = false +python-versions = "*" +files = [ + {file = "zizmor-0.8.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7ceba094f909b147427d816e7407145dfcf293ba7d5aacc1984d73d2856b3c2d"}, + {file = "zizmor-0.8.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:19a765851239def832d7f163994bc17717344a4bd6380965ce537e8d4d2d7e9a"}, + {file = "zizmor-0.8.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6db167359a0741e68a67440f746a1eecc821ed9ce25596effb377c0fcc0397e7"}, + {file = "zizmor-0.8.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2333f93e9c32e37dbd6303bc2561984ca9d81fe77950fc04e2b70d6f75bb867e"}, + {file = "zizmor-0.8.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d552f0930eb2de11f300906cb2d5acce5e389757a2de983eff262d98e77db3b"}, + {file = "zizmor-0.8.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9a6d88559160fa6b0917a9c72e9beb76a181f2509979100d0fd64f68a2ca444"}, + {file = "zizmor-0.8.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfac414362fc0e6dea7ad978579b699c85aae7aedeb9cb4d2ac109dff93d5d16"}, + {file = "zizmor-0.8.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5a12d91983076b19358c8beb677cabcf1edd7500605c0d5abab17cf2e2e627d2"}, + {file = "zizmor-0.8.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2f637ce89a41dddae555b9414e6292724fc0722adb64668df6d5d3568761b193"}, + {file = "zizmor-0.8.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:19799d366cd73b7753e47a00b5551a53e87003267706f12ac171de8785ddca26"}, + {file = "zizmor-0.8.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bf4b20a1c1465b66ad4bf8ada69f494fcd78f2baf1f8e72d34aa1a0a5b84180e"}, + {file = "zizmor-0.8.0-py3-none-win32.whl", hash = "sha256:58d19bf12cb79ac0f6d7cb006a4d5a6fc54dfea0cffb63b53ddc52c3b5e744d8"}, + {file = "zizmor-0.8.0-py3-none-win_amd64.whl", hash = "sha256:ddbcee8b39f681d59f1b1d83375f1abd71dc3f2a45f4988a1ee8afc990ae89c1"}, + {file = "zizmor-0.8.0.tar.gz", hash = "sha256:0a236717c9f6fdbace47c2dfdabdd963207e8101ecc6334ccf24205a98baef24"}, +] + [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "47d418b0ad57f239aaf79f8fc530c03ecd629fbb1758f0fd8dc97947884030a3" +content-hash = "fd34747afed4550ce046b24b93d07c4676db0df1c20efae253b52822aa5aaa7f" diff --git a/pyproject.toml b/pyproject.toml index 73e2f6f0d..c73276dc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ python = "^3.11" ruff = "^0.6.4" safety = "*" shellcheck-py = "*" +zizmor = "*" [tool.ruff] line-length = 100