From 4d4350f2b9b35cc89afe70b173f2b2a5aa332caa Mon Sep 17 00:00:00 2001 From: jrfnl Date: Wed, 17 Sep 2025 06:13:46 +0200 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/cs.yml | 26 ++++++++++----------- .github/workflows/label-merge-conflicts.yml | 2 +- .github/workflows/quicktest.yml | 12 +++++----- .github/workflows/test.yml | 12 +++++----- .github/workflows/update-website.yml | 8 +++---- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml index 09fd943..99d8326 100644 --- a/.github/workflows/cs.yml +++ b/.github/workflows/cs.yml @@ -21,10 +21,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: 'latest' coverage: none @@ -46,56 +46,56 @@ jobs: # Install dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1 with: # Bust the cache at least once a month - output format: YYYY-MM. custom-cache-suffix: $(date -u "+%Y-%m") # Validate the XSD and XML files against schema. - name: Validate Docs XSD against schema - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "DocsXsd/phpcsdocs.xsd" xsd-url: "https://www.w3.org/2012/04/XMLSchema.xsd" - name: Validate PHPCSDebug ruleset against schema - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "PHPCSDebug/ruleset.xml" xsd-file: "vendor/squizlabs/php_codesniffer/phpcs.xsd" - name: Validate docs against schema - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "PHPCSDebug/Docs/*/*Standard.xml" xsd-file: "DocsXsd/phpcsdocs.xsd" - name: Validate Project PHPCS ruleset against schema - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "phpcs.xml.dist" xsd-file: "vendor/squizlabs/php_codesniffer/phpcs.xsd" - name: "Validate PHPUnit < 10 config for use with PHPUnit 8" - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "phpunitlte9.xml.dist" xsd-file: "vendor/phpunit/phpunit/schema/8.5.xsd" - name: "Validate PHPUnit < 10 config for use with PHPUnit 9" - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "phpunitlte9.xml.dist" xsd-file: "vendor/phpunit/phpunit/schema/9.5.xsd" - name: "Validate PHPUnit 10+ config for use with PHPUnit 10" - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "phpunit.xml.dist" xsd-file: "vendor/phpunit/phpunit/schema/10.5.xsd" - name: "Validate PHPUnit 10+ config for use with PHPUnit 11" - uses: phpcsstandards/xmllint-validate@v1 + uses: phpcsstandards/xmllint-validate@0fd9c4a9046055f621fca4bbdccb8eab1fd59fdc # v1.0.1 with: pattern: "phpunit.xml.dist" xsd-file: "vendor/phpunit/phpunit/phpunit.xsd" @@ -118,7 +118,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # Updating the lists can fail intermittently, typically after Microsoft has released a new package. # This should not be blocking for this job, so ignore any errors from this step. @@ -132,7 +132,7 @@ jobs: # Show XML violations inline in the file diff. - name: Enable showing XML issues inline - uses: korelstar/xmllint-problem-matcher@v1 + uses: korelstar/xmllint-problem-matcher@1bd292d642ddf3d369d02aaa8b262834d61198c0 # v1.2.0 # Check code-style consistency of the XSD and XML files. - name: Check XSD code style diff --git a/.github/workflows/label-merge-conflicts.yml b/.github/workflows/label-merge-conflicts.yml index f3d0ceb..0dc313d 100644 --- a/.github/workflows/label-merge-conflicts.yml +++ b/.github/workflows/label-merge-conflicts.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Check PRs for merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3 + uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 with: dirtyLabel: "Status: has merge conflict" repoToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/quicktest.yml b/.github/workflows/quicktest.yml index fe90e03..d8fcb7c 100644 --- a/.github/workflows/quicktest.yml +++ b/.github/workflows/quicktest.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # Updating the lists can fail intermittently, typically after Microsoft has released a new package. # This should not be blocking for this job, so ignore any errors from this step. @@ -40,7 +40,7 @@ jobs: run: sudo apt-get install --no-install-recommends -y libxml2-utils - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: ${{ matrix.php }} ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On @@ -49,7 +49,7 @@ jobs: # Install dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1 with: # Bust the cache at least once a month - output format: YYYY-MM. custom-cache-suffix: $(date -u "+%Y-%m") @@ -120,7 +120,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # On stable PHPCS versions, allow for PHP deprecation notices. # Unit tests don't need to fail on those for stable releases where those issues won't get fixed anymore. @@ -134,7 +134,7 @@ jobs: fi - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: ${{ matrix.php }} ini-values: ${{ steps.set_ini.outputs.PHP_INI }} @@ -150,7 +150,7 @@ jobs: # Install dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1 with: # Bust the cache at least once a month - output format: YYYY-MM. custom-cache-suffix: $(date -u "+%Y-%m") diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 496d9bd..8ee741c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # Updating the lists can fail intermittently, typically after Microsoft has released a new package. # This should not be blocking for this job, so ignore any errors from this step. @@ -43,7 +43,7 @@ jobs: run: sudo apt-get install --no-install-recommends -y libxml2-utils - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: ${{ matrix.php }} ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On @@ -53,7 +53,7 @@ jobs: # Install dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1 with: composer-options: ${{ matrix.php == '8.5' && '--ignore-platform-req=php+' || '' }} # Bust the cache at least once a month - output format: YYYY-MM. @@ -174,7 +174,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup ini config id: set_ini @@ -188,7 +188,7 @@ jobs: fi - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: ${{ matrix.php }} ini-values: ${{ steps.set_ini.outputs.PHP_INI }} @@ -204,7 +204,7 @@ jobs: # Install dependencies and handle caching in one go. # @link https://github.com/marketplace/actions/install-php-dependencies-with-composer - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1 with: composer-options: ${{ matrix.php == '8.5' && '--ignore-platform-req=php+' || '' }} # Bust the cache at least once a month - output format: YYYY-MM. diff --git a/.github/workflows/update-website.yml b/.github/workflows/update-website.yml index 2343b5b..a06824e 100644 --- a/.github/workflows/update-website.yml +++ b/.github/workflows/update-website.yml @@ -48,12 +48,12 @@ jobs: fi - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: ref: ${{ steps.base_branch.outputs.BRANCH }} - name: Install PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # master with: php-version: 'latest' ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On, log_errors_max_len=0 @@ -83,13 +83,13 @@ jobs: fi - name: Check GitHub Pages status - uses: crazy-max/ghaction-github-status@v4 + uses: crazy-max/ghaction-github-status@fa6ac37620bc5d44b93e15caed498629665e9ff5 # v4.2.0 with: pages_threshold: major_outage - name: Deploy the website if: success() - uses: crazy-max/ghaction-github-pages@v4 + uses: crazy-max/ghaction-github-pages@df5cc2bfa78282ded844b354faee141f06b41865 # v4.2.0 with: build_dir: 'deploy' target_branch: 'gh-pages' From 12dc50563cacd1e166c506d5918138b8f0136aca Mon Sep 17 00:00:00 2001 From: jrfnl Date: Wed, 17 Sep 2025 06:13:55 +0200 Subject: [PATCH 2/2] Dependabot: update config This commit makes two changes to the Dependabot config: 1. It introduces a "cooldown" period for updates to a new major release of action runners. What this means, is that for updates to a new major, the Dependabot will be delayed by 10 days, which should give projects the chance to fix any "teething problems". 2. 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. 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 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5733780..3e76a99 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -27,3 +27,11 @@ updates: prefix: "GH Actions:" labels: - "Type: chores/QA" + cooldown: + semver-major-days: 10 + groups: + action-runners: + applies-to: version-updates + update-types: + - "minor" + - "patch"