From 05a52a7124c1d0cf28043da2852a580b51375d36 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 22 Sep 2025 08:27:49 +0200 Subject: [PATCH 1/2] Do not persist credentials during checkout to prevent exfiltration or accidental logging Based on this commit in Gitoxide: https://github.com/GitoxideLabs/gitoxide/pull/2187/commits/a235ac803598df05cefb2f3eff46598e42a16b96 --- .github/workflows/pr-labeler.yml | 1 + .github/workflows/push-e2e-img.yml | 2 ++ .github/workflows/push.yaml | 20 +++++++++++++++++++ .../workflows/test-client-fe-integration.yml | 3 +++ .github/workflows/test-e2e-blackbox.yml | 3 +++ .github/workflows/test-e2e-playwright.yml | 3 +++ 6 files changed, 32 insertions(+) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 67e7d28c01..e125080004 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -13,6 +13,7 @@ jobs: steps: - uses: actions/checkout@v5 with: + persist-credentials: false repository: 'gitbutlerapp/gitbutler' - uses: actions/labeler@v6 with: diff --git a/.github/workflows/push-e2e-img.yml b/.github/workflows/push-e2e-img.yml index df5b3ac7a7..f0d28389ef 100644 --- a/.github/workflows/push-e2e-img.yml +++ b/.github/workflows/push-e2e-img.yml @@ -12,6 +12,8 @@ jobs: permissions: write-all steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 7dba91151a..c324b56e10 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -20,6 +20,8 @@ jobs: rust: ${{ steps.filter.outputs.rust }} steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: dorny/paths-filter@v3 id: filter with: @@ -49,6 +51,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: ./.github/actions/init-env-node - run: pnpm prettier @@ -58,6 +62,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: ./.github/actions/init-env-node - run: pnpm lint @@ -67,6 +73,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: ./.github/actions/init-env-node - run: pnpm check @@ -76,6 +84,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: ./.github/actions/init-env-node - run: pnpm test @@ -89,6 +99,8 @@ jobs: CARGO_TERM_COLOR: always steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - run: cargo fmt --check --all - run: cargo check --workspace --all-targets @@ -102,6 +114,8 @@ jobs: CARGO_TERM_COLOR: always steps: - uses: actions/checkout@v5 + with: + persist-credentials: false # TODO(qix-): we have to exclude the app here for now because for some # TODO(qix-): reason it doesn't build with the docs feature enabled. - run: cargo doc --no-deps --all-features --document-private-items -p gitbutler-git @@ -114,6 +128,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: EmbarkStudios/cargo-deny-action@f2ba7abc2abebaf185c833c3961145a3c275caad # v2.0.13 with: command: check bans licenses sources @@ -129,6 +145,8 @@ jobs: shell: bash steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - name: Rust Cache uses: Swatinem/rust-cache@v2.8.0 with: @@ -186,6 +204,8 @@ jobs: CARGO_TERM_COLOR: always steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - name: Rust Cache uses: Swatinem/rust-cache@v2.8.0 with: diff --git a/.github/workflows/test-client-fe-integration.yml b/.github/workflows/test-client-fe-integration.yml index 461d271cd1..6c9a597f25 100644 --- a/.github/workflows/test-client-fe-integration.yml +++ b/.github/workflows/test-client-fe-integration.yml @@ -15,10 +15,13 @@ jobs: timeout-minutes: 60 steps: - uses: actions/checkout@v5 + with: + persist-credentials: false if: ${{ github.event_name != 'workflow_dispatch' }} - uses: actions/checkout@v5 if: ${{ github.event_name == 'workflow_dispatch' }} with: + persist-credentials: false ref: ${{ github.event.inputs.sha }} - name: Setup node environment uses: ./.github/actions/init-env-node diff --git a/.github/workflows/test-e2e-blackbox.yml b/.github/workflows/test-e2e-blackbox.yml index dec116afd5..1e8944af35 100644 --- a/.github/workflows/test-e2e-blackbox.yml +++ b/.github/workflows/test-e2e-blackbox.yml @@ -19,10 +19,13 @@ jobs: CARGO_TERM_COLOR: always steps: - uses: actions/checkout@v5 + with: + persist-credentials: false if: ${{ github.event_name != 'workflow_dispatch' }} - uses: actions/checkout@v5 if: ${{ github.event_name == 'workflow_dispatch' }} with: + persist-credentials: false ref: ${{ github.event.inputs.sha }} - name: Install Tauri OS dependencies run: | diff --git a/.github/workflows/test-e2e-playwright.yml b/.github/workflows/test-e2e-playwright.yml index 5bfcf5e06d..10ba70847a 100644 --- a/.github/workflows/test-e2e-playwright.yml +++ b/.github/workflows/test-e2e-playwright.yml @@ -27,10 +27,13 @@ jobs: GIT_CONFIG_GLOBAL: ${{ github.workspace }}/e2e/playwright/fixtures/.gitconfig steps: - uses: actions/checkout@v5 + with: + persist-credentials: false if: ${{ github.event_name != 'workflow_dispatch' }} - uses: actions/checkout@v5 if: ${{ github.event_name == 'workflow_dispatch' }} with: + persist-credentials: false ref: ${{ github.event.inputs.sha }} - name: Rust Cache uses: Swatinem/rust-cache@v2.8.0 From 74309c7bab6a32459d83954b27f9211786f55fd1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 22 Sep 2025 09:53:49 +0200 Subject: [PATCH 2/2] Add a workflow to check that all workflows don't persist credentials. `publish.yaml` is excluded just because testing it is more cumbersome, and it's nothing that untrusted parties can easily run. --- .github/workflows/push.yaml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index c324b56e10..cc6d2f1d19 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -212,3 +212,32 @@ jobs: shared-key: windows-rust-testing - name: 'cargo check' run: cargo check --workspace --all-targets --features windows + + # Check that all `actions/checkout` in CI jobs have `persist-credentials: false`. + check-no-persist-credentials: + runs-on: ubuntu-latest + + env: + GLOB: .github/workflows/*.@(yaml|yml) + + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + sparse-checkout: '.github/workflows' + - name: Generate workflows list to scan + run: | + shopt -s extglob + printf '%s\n' ${{ env.GLOB }} | grep -v .github/workflows/publish.yaml >workflows.list + cat workflows.list + echo "Note that publish.yaml is excluded until it's ensured to not need this feature" + - name: Scan workflows + run: | + shopt -s extglob + yq '.jobs.*.steps[] + | select(.uses == "actions/checkout@*" and .with.["persist-credentials"]? != false) + | {"file": filename, "line": line, "name": (.name // .uses)} + | .file + ":" + (.line | tostring) + ": " + .name + ' -- $(cat workflows.list) >query-output.txt + cat query-output.txt + test -z "$(