From 1efd6c9ba82cffd27f7e5a49d3e263b5b03e07f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 11:54:54 +0100 Subject: [PATCH 1/6] SEC: add cooldown period to dependabot settings --- .github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 963c3a6..e6e1f37 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: actions: patterns: - "*" + cooldown: + default-days: 7 From 7ee88af67a504bd05c052778d6cb454b48745c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 12:01:13 +0100 Subject: [PATCH 2/6] SEC: fix exploitable template-injection surface --- .github/workflows/publish.yml | 26 +++++++++++++------ .github/workflows/tox.yml | 47 ++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9e1c5a8..6d8be22 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -129,8 +129,10 @@ jobs: env: LOAD_BUILD_TARGETS_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicHl5YW1sPT02LjAuMiIsCiMgXQojIC8vLwppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCgppbXBvcnQgY2xpY2sKaW1wb3J0IHlhbWwKCk1BQ0hJTkVfVFlQRSA9IHsKICAgICJsaW51eCI6ICJ1YnVudHUtbGF0ZXN0IiwKICAgICJtYWNvcyI6ICJtYWNvcy1sYXRlc3QiLAogICAgIndpbmRvd3MiOiAid2luZG93cy1sYXRlc3QiLAogICAgIndpbmRvd3MtYXJtIjogIndpbmRvd3MtMTEtYXJtIiwKfQoKQ0lCV19CVUlMRCA9IG9zLmVudmlyb24uZ2V0KCJDSUJXX0JVSUxEIiwgIioiKQpDSUJXX0FSQ0hTID0gb3MuZW52aXJvbi5nZXQoIkNJQldfQVJDSFMiLCAiYXV0byIpCgoKQGNsaWNrLmNvbW1hbmQoKQpAY2xpY2sub3B0aW9uKCItLXRhcmdldHMiLCBkZWZhdWx0PSIiKQpkZWYgbG9hZF9idWlsZF90YXJnZXRzKHRhcmdldHMpOgogICAgIiIiU2NyaXB0IHRvIGxvYWQgY2lidWlsZHdoZWVsIHRhcmdldHMgZm9yIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93LiIiIgogICAgIyBMb2FkIGxpc3Qgb2YgdGFyZ2V0cwogICAgdGFyZ2V0cyA9IHlhbWwubG9hZCh0YXJnZXRzLCBMb2FkZXI9eWFtbC5CYXNlTG9hZGVyKQogICAgcHJpbnQoanNvbi5kdW1wcyh0YXJnZXRzLCBpbmRlbnQ9MikpCgogICAgIyBDcmVhdGUgbWF0cml4CiAgICBtYXRyaXggPSB7ImluY2x1ZGUiOiBbXX0KICAgIGZvciB0YXJnZXQgaW4gdGFyZ2V0czoKICAgICAgICBtYXRyaXhbImluY2x1ZGUiXS5hcHBlbmQoZ2V0X21hdHJpeF9pdGVtKHRhcmdldCkpCgogICAgIyBPdXRwdXQgbWF0cml4CiAgICBwcmludChqc29uLmR1bXBzKG1hdHJpeCwgaW5kZW50PTIpKQogICAgd2l0aCBvcGVuKG9zLmVudmlyb25bIkdJVEhVQl9PVVRQVVQiXSwgImEiKSBhcyBmOgogICAgICAgIGYud3JpdGUoZiJtYXRyaXg9e2pzb24uZHVtcHMobWF0cml4KX1cbiIpCgoKZGVmIGdldF9vcyh0YXJnZXQpOgogICAgaWYgIm1hY29zIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIE1BQ0hJTkVfVFlQRVsibWFjb3MiXQogICAgaWYgIndpbl9hcm0iIGluIHRhcmdldDoKICAgICAgICByZXR1cm4gTUFDSElORV9UWVBFWyJ3aW5kb3dzLWFybSJdCiAgICBpZiAid2luIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIE1BQ0hJTkVfVFlQRVsid2luZG93cyJdCiAgICByZXR1cm4gTUFDSElORV9UWVBFWyJsaW51eCJdCgoKZGVmIGdldF9jaWJ3X2J1aWxkKHRhcmdldCk6CiAgICBpZiB0YXJnZXQgaW4geyJsaW51eCIsICJtYWNvcyIsICJ3aW5kb3dzIn06CiAgICAgICAgcmV0dXJuIENJQldfQlVJTEQKICAgIHJldHVybiB0YXJnZXQKCgpkZWYgZ2V0X2NpYndfYXJjaHModGFyZ2V0KToKICAgICIiIgogICAgSGFuZGxlIG5vbi1uYXRpdmUgYXJjaGl0ZWN0dXJlcwoKICAgIGNpYncgYWxsb3dzIHJ1bm5pbmcgbm9uLW5hdGl2ZSBidWlsZHMgb24gdmFyaW91cyBwbGF0Zm9ybXM6CiAgICBodHRwczovL2NpYnVpbGR3aGVlbC5weXBhLmlvL2VuL3N0YWJsZS9vcHRpb25zLyNhcmNocwoKICAgIFRoaXMgbG9naWMgb3ZlcnJpZGVzIHRoZSAiYXV0byIgZmxhZyBiYXNlZCBvbiBPUyBhbmQgYSBsaXN0IG9mIHN1cHBvcnRlZAogICAgbm9uLW5hdGl2ZSBhcmNoIGlmIGEgbm9uLW5hdGl2ZSBhcmNoIGlzIGdpdmVuIGZvciBhIHBhcnRpY3VsYXIgcGxhdGZvcm0gaW4KICAgIHRhcmdldHMsIHJhdGhlciB0aGFuIHRoZSB1c2VyIGhhdmluZyB0byBkbyB0aGlzIG1hbnVhbGx5LgogICAgIiIiCiAgICBwbGF0Zm9ybV9hcmNocyA9IHsKICAgICAgICAjIFdlIG5vdyBjcm9zcyBjb21waWxlIHg4Nl82NCBvbiBhcm02NCBieSBkZWZhdWx0CiAgICAgICAgIm1hY29zIjogWyJ1bml2ZXJzYWwyIiwgIng4Nl82NCJdLAogICAgICAgICMgVGhpcyBpcyBhIGxpc3Qgb2Ygc3VwcG9ydGVkIGV1bXVsYXRlZCBhcmNoZXMgb24gbGludXgKICAgICAgICAibGludXgiOiBbImFhcmNoNjQiLCAicHBjNjRsZSIsICJzMzkweCIsICJhcm12N2wiXSwKICAgIH0KICAgIGZvciBwbGF0Zm9ybSwgYXJjaHMgaW4gcGxhdGZvcm1fYXJjaHMuaXRlbXMoKToKICAgICAgICBpZiBwbGF0Zm9ybSBpbiB0YXJnZXQ6CiAgICAgICAgICAgIGZvciBhcmNoIGluIGFyY2hzOgogICAgICAgICAgICAgICAgaWYgdGFyZ2V0LmVuZHN3aXRoKGFyY2gpOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBhcmNoCgogICAgIyBJZiBubyBleHBsaWN0IGFyY2ggaGFzIGJlZW4gc3BlY2lmaWVkIGJ1aWxkIGJvdGggYXJtNjQgYW5kIHg4Nl82NCBvbiBtYWNvcwogICAgaWYgIm1hY29zIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIG9zLmVudmlyb24uZ2V0KCJDSUJXX0FSQ0hTIiwgImFybTY0IHg4Nl82NCIpCgogICAgcmV0dXJuIENJQldfQVJDSFMKCgpkZWYgZ2V0X2FydGlmYWN0X25hbWUodGFyZ2V0KToKICAgIGFydGlmYWN0X25hbWUgPSByZS5zdWIociJbXFwgLzo8PnwqP1wiJ10iLCAiLSIsIHRhcmdldCkKICAgIGFydGlmYWN0X25hbWUgPSByZS5zdWIociItKyIsICItIiwgYXJ0aWZhY3RfbmFtZSkKICAgIHJldHVybiBhcnRpZmFjdF9uYW1lCgoKZGVmIGdldF9tYXRyaXhfaXRlbSh0YXJnZXQpOgogICAgZXh0cmFfdGFyZ2V0X2FyZ3MgPSB7fQogICAgaWYgaXNpbnN0YW5jZSh0YXJnZXQsIGRpY3QpOgogICAgICAgIGV4dHJhX3RhcmdldF9hcmdzID0gdGFyZ2V0CiAgICAgICAgdGFyZ2V0ID0gZXh0cmFfdGFyZ2V0X2FyZ3MucG9wKCJ0YXJnZXQiKQogICAgcmV0dXJuIHsKICAgICAgICAidGFyZ2V0IjogdGFyZ2V0LAogICAgICAgICJydW5zLW9uIjogZ2V0X29zKHRhcmdldCksCiAgICAgICAgIkNJQldfQlVJTEQiOiBnZXRfY2lid19idWlsZCh0YXJnZXQpLAogICAgICAgICJDSUJXX0FSQ0hTIjogZ2V0X2NpYndfYXJjaHModGFyZ2V0KSwKICAgICAgICAiYXJ0aWZhY3QtbmFtZSI6IGdldF9hcnRpZmFjdF9uYW1lKHRhcmdldCksCiAgICAgICAgKipleHRyYV90YXJnZXRfYXJncywKICAgIH0KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9hZF9idWlsZF90YXJnZXRzKCkK - id: set-outputs - run: pipx run load_build_targets.py --targets "${{ inputs.targets }}" + run: pipx run load_build_targets.py --targets "${INPUTS_TARGETS}" shell: sh + env: + INPUTS_TARGETS: ${{ inputs.targets }} - id: set-upload run: | if [ $UPLOAD_TO_PYPI == "true" ] || [ $UPLOAD_TAG == "true" ]; @@ -171,21 +173,23 @@ jobs: - name: Parse dependency groups shell: bash run: | - echo "space_sep_groups=$( python -c "print('${{ inputs.test_groups }}'.replace(',', ' '))" )" >> "$GITHUB_ENV" + echo "space_sep_groups=$( python -c "print('${INPUTS_TEST_GROUPS}'.replace(',', ' '))" )" >> "$GITHUB_ENV" + env: + INPUTS_TEST_GROUPS: ${{ inputs.test_groups }} - name: Configure cibuildwheel shell: bash run: | - if [ -n "${{ inputs.test_extras }}" ]; + if [ -n "${INPUTS_TEST_EXTRAS}" ]; then - echo "CIBW_TEST_EXTRAS=${{ inputs.test_extras }}" >> $GITHUB_ENV + echo "CIBW_TEST_EXTRAS=${INPUTS_TEST_EXTRAS}" >> $GITHUB_ENV fi - if [ -n "${{ inputs.test_groups }}" ]; + if [ -n "${INPUTS_TEST_GROUPS}" ]; then echo "CIBW_TEST_GROUPS=$space_sep_groups" >> $GITHUB_ENV fi set +e IFS='' read -r -d '' test_command <<"EOF" - ${{ inputs.test_command }} + ${INPUTS_TEST_COMMAND} EOF set -e if [ -n "$test_command" ]; @@ -195,6 +199,10 @@ jobs: echo "EOF" >> $GITHUB_ENV fi cat $GITHUB_ENV + env: + INPUTS_TEST_EXTRAS: ${{ inputs.test_extras }} + INPUTS_TEST_GROUPS: ${{ inputs.test_groups }} + INPUTS_TEST_COMMAND: ${{ inputs.test_command }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 if: ${{ inputs.env != '' }} with: @@ -203,11 +211,12 @@ jobs: if: ${{ inputs.env != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ inputs.env }}" + pipx run set_env.py "${INPUTS_ENV}" rm set_env.py shell: sh env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + INPUTS_ENV: ${{ inputs.env }} - name: Run cibuildwheel uses: pypa/cibuildwheel@298ed2fb2c105540f5ed055e8a6ad78d82dd3a7e # v3.3.1 with: @@ -239,11 +248,12 @@ jobs: if: ${{ inputs.env != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ inputs.env }}" + pipx run set_env.py "${INPUTS_ENV}" rm set_env.py shell: sh env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + INPUTS_ENV: ${{ inputs.env }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index c5b9873..21bd510 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -132,18 +132,33 @@ jobs: - run: cat tox_matrix.py - id: set-outputs run: | - pipx run tox_matrix.py --envs "${{ inputs.envs }}" --libraries "${{ inputs.libraries }}" \ - --posargs "${{ inputs.posargs }}" --toxdeps "${{ inputs.toxdeps }}" \ - --toxargs "${{ inputs.toxargs }}" --pytest "${{ inputs.pytest }}" \ + pipx run tox_matrix.py --envs "${INPUTS_ENVS}" --libraries "${INPUTS_LIBRARIES}" \ + --posargs "${INPUTS_POSARGS}" --toxdeps "${INPUTS_TOXDEPS}" \ + --toxargs "${INPUTS_TOXARGS}" --pytest "${{ inputs.pytest }}" \ --pytest-results-summary "${{ inputs.pytest-results-summary }}" \ - --coverage "${{ inputs.coverage }}" --conda "${{ inputs.conda }}" \ - --setenv "${{ inputs.setenv }}" \ - --display "${{ inputs.display }}" --cache-path "${{ inputs.cache-path }}" \ - --cache-key "${{ inputs.cache-key }}" --cache-restore-keys "${{ inputs.cache-restore-keys }}" \ - --artifact-path "${{ inputs.artifact-path }}" \ - --runs-on "${{ inputs.runs-on }}" --default-python "${{ inputs.default_python }}" \ + --coverage "${INPUTS_COVERAGE}" --conda "${INPUTS_CONDA}" \ + --setenv "${INPUTS_SETENV}" \ + --display "${{ inputs.display }}" --cache-path "${INPUTS_CACHE_PATH}" \ + --cache-key "${INPUTS_CACHE_KEY}" --cache-restore-keys "${INPUTS_CACHE_RESTORE_KEYS}" \ + --artifact-path "${INPUTS_ARTIFACT_PATH}" \ + --runs-on "${INPUTS_RUNS_ON}" --default-python "${INPUTS_DEFAULT_PYTHON}" \ --timeout-minutes "${{ inputs.timeout-minutes }}" shell: sh + env: + INPUTS_ENVS: ${{ inputs.envs }} + INPUTS_LIBRARIES: ${{ inputs.libraries }} + INPUTS_POSARGS: ${{ inputs.posargs }} + INPUTS_TOXDEPS: ${{ inputs.toxdeps }} + INPUTS_TOXARGS: ${{ inputs.toxargs }} + INPUTS_COVERAGE: ${{ inputs.coverage }} + INPUTS_CONDA: ${{ inputs.conda }} + INPUTS_SETENV: ${{ inputs.setenv }} + INPUTS_CACHE_PATH: ${{ inputs.cache-path }} + INPUTS_CACHE_KEY: ${{ inputs.cache-key }} + INPUTS_CACHE_RESTORE_KEYS: ${{ inputs.cache-restore-keys }} + INPUTS_ARTIFACT_PATH: ${{ inputs.artifact-path }} + INPUTS_RUNS_ON: ${{ inputs.runs-on }} + INPUTS_DEFAULT_PYTHON: ${{ inputs.default_python }} outputs: matrix: ${{ steps.set-outputs.outputs.matrix }} @@ -211,19 +226,27 @@ jobs: if: ${{ matrix.setenv != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ matrix.setenv }}" + pipx run set_env.py "${MATRIX_SETENV}" rm set_env.py env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + MATRIX_SETENV: ${{ matrix.setenv }} - name: Setup headless display if: ${{ matrix.display == 'true' }} uses: pyvista/setup-headless-display-action@7d84ae825e6d9297a8e99bdbbae20d1b919a0b19 # v4.2 - name: Install tox - run: python -m pip install --upgrade tox ${{ matrix.toxdeps }} + run: python -m pip install --upgrade tox ${MATRIX_TOXDEPS} + env: + MATRIX_TOXDEPS: ${{ matrix.toxdeps }} - - run: python -m tox -e ${{ matrix.toxenv }} ${{ matrix.toxargs }} -- ${{ matrix.pytest_flag }} ${{ matrix.posargs }} + - run: python -m tox -e ${MATRIX_TOXENV} ${MATRIX_TOXARGS} -- ${MATRIX_PYTEST_FLAG} ${MATRIX_POSARGS} + env: + MATRIX_TOXENV: ${{ matrix.toxenv }} + MATRIX_TOXARGS: ${{ matrix.toxargs }} + MATRIX_PYTEST_FLAG: ${{ matrix.pytest_flag }} + MATRIX_POSARGS: ${{ matrix.posargs }} - if: ${{ (success() || failure()) && matrix.artifact-path != '' }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 From b10a484b5f8f7b78ca820297a6fd0f6039a221b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 12:04:01 +0100 Subject: [PATCH 3/6] SEC: avoid leaking credentials --- .github/workflows/publish.yml | 2 ++ .github/workflows/publish_pure_python.yml | 4 +++- .github/workflows/pull_from_upstream.yml | 1 + .github/workflows/tox.yml | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6d8be22..6e8e595 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -160,6 +160,7 @@ jobs: lfs: true submodules: ${{ inputs.submodules }} ref: ${{ inputs.checkout_ref }} + persist-credentials: false - name: Get machine arch if: ${{ runner.os == 'Linux' }} id: uname_m @@ -259,6 +260,7 @@ jobs: fetch-depth: 0 lfs: true submodules: ${{ inputs.submodules }} + persist-credentials: false - name: Install dependencies if: ${{ inputs.libraries != '' }} uses: ConorMacBride/install-package@3e7ad059e07782ee54fa35f827df52aae0626f30 # v1.1.0 diff --git a/.github/workflows/publish_pure_python.yml b/.github/workflows/publish_pure_python.yml index c85175c..643706d 100644 --- a/.github/workflows/publish_pure_python.yml +++ b/.github/workflows/publish_pure_python.yml @@ -114,17 +114,19 @@ jobs: if: ${{ inputs.env != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ inputs.env }}" + pipx run set_env.py "${INPUTS_ENV}" rm set_env.py shell: sh env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + INPUTS_ENV: ${{ inputs.env }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 lfs: true submodules: ${{ inputs.submodules }} ref: ${{ inputs.checkout_ref }} + persist-credentials: false - name: Install dependencies if: ${{ inputs.libraries != '' }} uses: ConorMacBride/install-package@3e7ad059e07782ee54fa35f827df52aae0626f30 # v1.1.0 diff --git a/.github/workflows/pull_from_upstream.yml b/.github/workflows/pull_from_upstream.yml index 60b85cd..a143de3 100644 --- a/.github/workflows/pull_from_upstream.yml +++ b/.github/workflows/pull_from_upstream.yml @@ -18,6 +18,7 @@ jobs: # Checkout the repository where the workflow is running ref: main fetch-depth: 0 + persist-credentials: false - name: Set up git run: | diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 21bd510..3ae9957 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -182,6 +182,7 @@ jobs: lfs: true submodules: ${{ inputs.submodules }} ref: ${{ inputs.checkout_ref }} + persist-credentials: false - name: Cache ${{ matrix.cache_key }} if: ${{ matrix.cache-path != '' && matrix.cache-key != '' }} @@ -289,6 +290,7 @@ jobs: lfs: true submodules: ${{ inputs.submodules }} ref: ${{ inputs.checkout_ref }} + persist-credentials: false - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: pattern: coverage-data-${{ github.run_id }}-* From b7e7ebaa141a1abb0c5d7885e7bcc4fcc7245074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 11:54:05 +0100 Subject: [PATCH 4/6] SEC: disable default gha permissions --- .github/workflows/test_publish.yml | 2 ++ .github/workflows/test_publish_pure_python.yml | 2 ++ .github/workflows/test_tox.yml | 2 ++ .github/workflows/update_tag.yml | 2 ++ 4 files changed, 8 insertions(+) diff --git a/.github/workflows/test_publish.yml b/.github/workflows/test_publish.yml index 76c1d0c..bfc2247 100644 --- a/.github/workflows/test_publish.yml +++ b/.github/workflows/test_publish.yml @@ -15,6 +15,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: release_default: uses: ./.github/workflows/publish.yml diff --git a/.github/workflows/test_publish_pure_python.yml b/.github/workflows/test_publish_pure_python.yml index c45e135..81823a3 100644 --- a/.github/workflows/test_publish_pure_python.yml +++ b/.github/workflows/test_publish_pure_python.yml @@ -15,6 +15,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: release: uses: ./.github/workflows/publish_pure_python.yml diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index 86cdc56..5b63f66 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -19,6 +19,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: test_pyos: uses: ./.github/workflows/tox.yml diff --git a/.github/workflows/update_tag.yml b/.github/workflows/update_tag.yml index be4ca6b..cfa4b3c 100644 --- a/.github/workflows/update_tag.yml +++ b/.github/workflows/update_tag.yml @@ -5,6 +5,8 @@ on: tags: - "v*" +permissions: {} + jobs: update-majorver: name: Update Major Version Tag From 3606eca2f0684e5c5b4a3b9929e0c863b2d8ba42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 12:15:34 +0100 Subject: [PATCH 5/6] amend --- .github/workflows/test_tox.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index 5b63f66..77d8876 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -19,7 +19,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: {} +# permissions: {} jobs: test_pyos: From 987fc93e9a29914382481bff4bf2c04ba96a0db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 12:19:52 +0100 Subject: [PATCH 6/6] revert --- .github/workflows/test_tox.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test_tox.yml b/.github/workflows/test_tox.yml index 77d8876..86cdc56 100644 --- a/.github/workflows/test_tox.yml +++ b/.github/workflows/test_tox.yml @@ -19,8 +19,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# permissions: {} - jobs: test_pyos: uses: ./.github/workflows/tox.yml