From a56ebc224dcb5a5bc7ea3d24dba60227483755c1 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 8 Dec 2025 20:49:02 +0100 Subject: [PATCH 1/2] GH Actions: "pin" all action runners Recently there has been more and more focus on securing GH Actions workflows - in part due to some incidents. The problem with "unpinned" action runners is as follows: * Tags are mutable, which means that a tag could point to a safe commit today, but to a malicious commit tomorrow. Note that GitHub is currently beta-testing a new "immutable releases" feature (= tags and release artifacts can not be changed anymore once the release is published), but whether that has much effect depends on the ecosystem of the packages using the feature. Aside from that, it will likely take years before all projects adopt _immutable releases_. * Action runners often don't even point to a tag, but to a branch, making the used action runner a moving target. _Note: this type of "floating major" for action runners used to be promoted as good practice when the ecosystem was "young". Insights have since changed._ While it is convenient to use "floating majors" of action runners, as this means you only need to update the workflows on a new major release of the action runner, the price is higher risk of malicious code being executed in workflows. Dependabot, by now, can automatically submit PRs to update pinned action runners too, as long as the commit-hash pinned runner is followed by a comment listing the released version the commit is pointing to. So, what with Dependabot being capable of updating workflows with pinned action runners, I believe it is time to update the workflows to the _current_ best practice of using commit-hash pinned action runners. The downside of this change is that there will be more frequent Dependabot PRs. If this would become a burden/irritating, the following mitigations can be implemented: 1. Updating the Dependabot config to group updates instead of sending individual PRs per action runner. 2. A workflow to automatically merge Dependabot PRs as long as CI passes. Ref: https://docs.github.com/en/actions/reference/security/secure-use#using-third-party-actions --- .github/workflows/release.yml | 10 +++++----- .github/workflows/reusable-build-binary.yml | 8 ++++---- .github/workflows/test.yml | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c13e682..c32a559 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,15 +50,15 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Download PHAR file - uses: actions/download-artifact@v8 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: parallel-lint-phar - name: Setup PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: php-version: ${{ matrix.php }} ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On, zend.assertions=1 @@ -76,12 +76,12 @@ jobs: steps: - name: Download PHAR file - uses: actions/download-artifact@v8 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: parallel-lint-phar - name: Draft Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: tag_name: ${{ github.ref_name }} name: Release ${{ github.ref_name }} diff --git a/.github/workflows/reusable-build-binary.yml b/.github/workflows/reusable-build-binary.yml index 1833566..d477a25 100644 --- a/.github/workflows/reusable-build-binary.yml +++ b/.github/workflows/reusable-build-binary.yml @@ -10,10 +10,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: php-version: 8.2 extensions: exif, phar, openssl, sodium @@ -25,7 +25,7 @@ jobs: fail-fast: true - name: Install Composer dependencies - uses: ramsey/composer-install@v4 + uses: ramsey/composer-install@2b6adcf6fa51986b4a64e960e812c1bf5a38f237 # v4 with: composer-options: "--no-dev" # Bust the cache at least once a month - output format: YYYY-MM. @@ -46,7 +46,7 @@ jobs: run: php box.phar info -l parallel-lint.phar - name: Upload PHAR to workflow summary - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: parallel-lint-phar path: ./parallel-lint.phar diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1db8707..514fe43 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,17 +21,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: php-version: 'latest' coverage: none tools: cs2pr - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Install Composer dependencies - uses: ramsey/composer-install@v4 + uses: ramsey/composer-install@2b6adcf6fa51986b4a64e960e812c1bf5a38f237 # v4 with: # Bust the cache at least once a month - output format: YYYY-MM. custom-cache-suffix: $(date -u "+%Y-%m") @@ -77,10 +77,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: php-version: ${{ matrix.php }} ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On, zend.assertions=1 @@ -93,14 +93,14 @@ jobs: - name: Install Composer dependencies if: ${{ matrix.php != '8.6' }} - uses: ramsey/composer-install@v4 + uses: ramsey/composer-install@2b6adcf6fa51986b4a64e960e812c1bf5a38f237 # v4 with: # Bust the cache at least once a month - output format: YYYY-MM. custom-cache-suffix: $(date -u "+%Y-%m") - name: "Install Composer dependencies (PHP nightly, ignore PHP reqs)" if: ${{ matrix.php == '8.6' }} - uses: ramsey/composer-install@v4 + uses: ramsey/composer-install@2b6adcf6fa51986b4a64e960e812c1bf5a38f237 # v4 with: composer-options: --ignore-platform-req=php custom-cache-suffix: $(date -u "+%Y-%m") @@ -125,7 +125,7 @@ jobs: run: composer test10 - name: Download PHAR file - uses: actions/download-artifact@v8 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: parallel-lint-phar From 10f3550247f7c58c91cb99ecf091b123947a408d Mon Sep 17 00:00:00 2001 From: jrfnl Date: Sat, 20 Sep 2025 04:14:59 +0200 Subject: [PATCH 2/2] Dependabot: update config This commit makes the following change to the Dependabot config: * It introduces a "group". By default Dependabot raises individual PRs for each update. Now, it will group updates to new minor or patch release for all action runners into a single PR. Updates to new major releases of action runners will still be raised as individual PRs. * It changes the configuration from weekly to bi-weekly as what with the pinned action runners, Dependabot PRs will come more frequently. Refs: * https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/optimizing-pr-creation-version-updates * https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference --- .github/dependabot.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a1d5171..f65a687 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,9 +8,16 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" + interval: "cron" + cronjob: "10 22 5,20 * *" # At 22:10, every 5th and 20th day of the month. open-pull-requests-limit: 5 commit-message: prefix: "GH Actions:" labels: - "Type: chores/QA" + groups: + action-runners: + applies-to: version-updates + update-types: + - "minor" + - "patch"