From 23e7fe4916e025afecb85f53ede91838190db1a3 Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:01:05 +0200 Subject: [PATCH 1/7] Add and use workflow:audit --- .github/workflows/checks.yml | 22 ++++++++++ .github/workflows/fast-tests-extension.yml | 20 +--------- .github/zizmor.yml => .zizmor.yml | 0 doc/changes/unreleased.md | 5 +++ exasol/toolbox/config.py | 8 ++++ exasol/toolbox/nox/_workflow.py | 20 ++++++++++ .../templates/github/workflows/checks.yml | 23 +++++++++++ test/unit/config_test.py | 1 + test/unit/nox/_workflow_test.py | 40 ++++++++++++++++++- 9 files changed, 119 insertions(+), 20 deletions(-) rename .github/zizmor.yml => .zizmor.yml (100%) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index ebe6491e3..9a4aa271d 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -228,3 +228,25 @@ jobs: id: check-workflows if: ${{ !startsWith(github.head_ref || github.ref_name, 'release/prepare-') }} run: poetry run -- nox -s workflow:check -- all + audit-workflows: + name: Audit Workflows + runs-on: "ubuntu-24.04" + permissions: + contents: read + steps: + - name: Check out Repository + id: check-out-repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Set up Python & Poetry Environment + id: set-up-python-and-poetry-environment + uses: exasol/python-toolbox/.github/actions/python-environment@v9 + with: + python-version: "3.10" + poetry-version: "2.3.0" + + - name: Check Workflows + id: check-workflows + run: poetry run -- nox -s workflow:audit diff --git a/.github/workflows/fast-tests-extension.yml b/.github/workflows/fast-tests-extension.yml index 0c8dfca7f..88f645cdc 100644 --- a/.github/workflows/fast-tests-extension.yml +++ b/.github/workflows/fast-tests-extension.yml @@ -25,22 +25,4 @@ jobs: - name: Lint Imports id: lint-imports - run: poetry run -- nox -s lint:import - - # This will be moved to a standard check in the checks.yml in: - # https://github.com/exasol/python-toolbox/issues/811 - lint-github-actions: - name: Lint GitHub Actions - runs-on: ubuntu-24.04 - steps: - - name: Check out Repository - id: check-out-repository - uses: actions/checkout@v6 - with: - persist-credentials: false - - - name: Lint GitHub actions with Zizmor - id: lint-github-actions - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 - with: - advanced-security: false + run: poetry run -- nox -s lint:import \ No newline at end of file diff --git a/.github/zizmor.yml b/.zizmor.yml similarity index 100% rename from .github/zizmor.yml rename to .zizmor.yml diff --git a/doc/changes/unreleased.md b/doc/changes/unreleased.md index dcc829b04..4fcaebf47 100644 --- a/doc/changes/unreleased.md +++ b/doc/changes/unreleased.md @@ -9,9 +9,14 @@ so ITDE-related test flows use the configured Exasol baseline and unit-test help * #744: Updated nox DB-version handling to use `BaseConfig.minimum_exasol_version` instead hardcoded `7.1.9` +## Feature + +* #878: Added Nox session `workflow:audit` which uses `zizmor` and added it in `checks.yml` + ## Refactoring * #744: Extracted shared minimum-version selection logic into `minimum_declared_version()` + ## Security * #867: Fixed zizmor linting results diff --git a/exasol/toolbox/config.py b/exasol/toolbox/config.py index 126a44587..aabbe8a00 100644 --- a/exasol/toolbox/config.py +++ b/exasol/toolbox/config.py @@ -351,3 +351,11 @@ def github_workflow_patcher_yaml(self) -> Path | None: if workflow_patcher_yaml.is_file(): return workflow_patcher_yaml return None + + @computed_field # type: ignore[misc] + @property + def zizmor_config_path(self) -> Path: + """ + Path where the zizmor configuration file for the project is stored. + """ + return self.root_path / ".zizmor.yml" \ No newline at end of file diff --git a/exasol/toolbox/nox/_workflow.py b/exasol/toolbox/nox/_workflow.py index 2c07c0093..bde901ba5 100644 --- a/exasol/toolbox/nox/_workflow.py +++ b/exasol/toolbox/nox/_workflow.py @@ -64,3 +64,23 @@ def generate_workflow(session: Session) -> None: workflow_choice=args.workflow_choice, config=PROJECT_CONFIG, ).generate_workflows() + + +@nox.session(name="workflow:audit", python=False) +def audit_workflows(session: Session) -> None: + """ + Audit GitHub actions & workflows with zizmor. + This Nox session passes through additional arguments that zizmor supports. + In some cases, zizmor findings can be automatically fixed with `--fix=safe`. + """ + config_path = PROJECT_CONFIG.zizmor_config_path + if not config_path.is_file(): + raise FileNotFoundError(f"{config_path} must exist.") + + session.run( + "zizmor", + "--config", + config_path, + *session.posargs, + PROJECT_CONFIG.root_path, + ) diff --git a/exasol/toolbox/templates/github/workflows/checks.yml b/exasol/toolbox/templates/github/workflows/checks.yml index 24103ae69..d78ad0456 100644 --- a/exasol/toolbox/templates/github/workflows/checks.yml +++ b/exasol/toolbox/templates/github/workflows/checks.yml @@ -226,3 +226,26 @@ jobs: - name: Check Workflows id: check-workflows run: poetry run -- nox -s workflow:check -- all + + audit-workflows: + name: Audit Workflows + runs-on: "(( os_version ))" + permissions: + contents: read + steps: + - name: Check out Repository + id: check-out-repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Set up Python & Poetry Environment + id: set-up-python-and-poetry-environment + uses: exasol/python-toolbox/.github/actions/python-environment@v9 + with: + python-version: "(( minimum_python_version ))" + poetry-version: "(( dependency_manager_version ))" + + - name: Check Workflows + id: check-workflows + run: poetry run -- nox -s workflow:audit diff --git a/test/unit/config_test.py b/test/unit/config_test.py index d87c0a97b..3115d0632 100644 --- a/test/unit/config_test.py +++ b/test/unit/config_test.py @@ -77,6 +77,7 @@ def test_works_as_defined(tmp_path, test_project_config_factory): "root_path": root_path, "sonar_code_path": Path("exasol/test"), "source_code_path": root_path / "exasol" / "test", + "zizmor_config_path": root_path / ".zizmor.yml", } @staticmethod diff --git a/test/unit/nox/_workflow_test.py b/test/unit/nox/_workflow_test.py index 55ec74c10..b6183c7ea 100644 --- a/test/unit/nox/_workflow_test.py +++ b/test/unit/nox/_workflow_test.py @@ -6,6 +6,7 @@ from exasol.toolbox.config import BaseConfig from exasol.toolbox.nox._workflow import ( + audit_workflows, check_workflow, generate_workflow, ) @@ -32,7 +33,8 @@ def github_workflow_patcher_yaml(self) -> None: @pytest.fixture def nox_session_runner_posargs(request): - return [request.param] + value = request.param + return list(value) if isinstance(value, (list, tuple)) else [value] class TestGenerateWorkflow: @@ -144,3 +146,39 @@ def test_raises_session_quit_when_workflows_are_out_of_date( "- report\n" "- slow-checks" ) + + +class TestAuditWorkflows: + @staticmethod + @pytest.mark.parametrize( + "nox_session_runner_posargs", + [["--config-file", "custom.yml", "--no-progress"]], + indirect=["nox_session_runner_posargs"], + ) + def test_passes_through_extra_arguments( + nox_session, + project_config_without_patcher, + nox_session_runner_posargs, + ): + config_path = project_config_without_patcher.root_path / ".zizmor.yml" + config_path.parent.mkdir(parents=True, exist_ok=True) + config_path.write_text("rules: []\n") + + with ( + patch( + "exasol.toolbox.nox._workflow.PROJECT_CONFIG", + new=project_config_without_patcher, + ), + patch("nox.sessions.Session.run") as run_mock, + ): + audit_workflows(nox_session) + + run_mock.assert_called_once_with( + "zizmor", + "--config", + config_path, + "--config-file", + "custom.yml", + "--no-progress", + project_config_without_patcher.root_path, + ) From 1585a52ce87b3c370137b40f196160e6b6a3ab23 Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:25:08 +0200 Subject: [PATCH 2/7] Add documentation for new feature --- .../features/managing_dependencies.rst | 26 +++++++++++++++++ .../ignore_zizmor_findings.rst | 28 +++++++++++++++++++ doc/user_guide/troubleshooting/index.rst | 1 + 3 files changed, 55 insertions(+) create mode 100644 doc/user_guide/troubleshooting/ignore_zizmor_findings.rst diff --git a/doc/user_guide/features/managing_dependencies.rst b/doc/user_guide/features/managing_dependencies.rst index cc4a349a7..01d5e5632 100644 --- a/doc/user_guide/features/managing_dependencies.rst +++ b/doc/user_guide/features/managing_dependencies.rst @@ -15,3 +15,29 @@ Managing Dependencies and Vulnerabilities | | | that have been resolved in | | | | comparison to the last release. | +------------------------------+----------------+-------------------------------------+ +| ``workflow:audit`` | ``checks.yml`` | Uses ``zizmor`` to audit GitHub | +| | | actions and workflows for security | +| | | issues and accepts extra zizmor | +| | | arguments. See | +| | | :ref:`zizmor_configuration` for | +| | | configuration details. | ++------------------------------+----------------+-------------------------------------+ + +.. _zizmor_configuration: + +Configuring Zizmor +------------------ + +``workflow:audit`` uses `zizmor `__ to audit GitHub +Actions and workflows. Zizmor reads its project configuration from a file named +``.zizmor.yml`` in the repository root. + +As a starting point, copy the template shipped with the PTB: + +.. literalinclude:: ../../../exasol/toolbox/templates/github/zizmor.yml + :language: yaml + +For details on the available audit and configuration options, see the +`zizmor documentation `__. + +For how to ignore accepted findings, see :ref:`ignore_zizmor_findings`. diff --git a/doc/user_guide/troubleshooting/ignore_zizmor_findings.rst b/doc/user_guide/troubleshooting/ignore_zizmor_findings.rst new file mode 100644 index 000000000..fbed3293d --- /dev/null +++ b/doc/user_guide/troubleshooting/ignore_zizmor_findings.rst @@ -0,0 +1,28 @@ +.. _ignore_zizmor_findings: + +Ignoring Zizmor Findings +======================== + +`zizmor `__ can automatically fix some findings. The +``--fix`` flag accepts three modes: + +* ``--fix=safe`` applies only safe fixes. This is the default. +* ``--fix=unsafe-only`` applies only unsafe fixes, meaning fixes that may be + correct but require human review because they can affect semantics. +* ``--fix=all`` applies both safe and unsafe fixes. + +When you are first enabling ``workflow:audit``, it can be practical to start with +a broader ``.zizmor.yml`` configuration and then tighten it over time. +However, once a finding is understood, prefer ignoring the specific line that +triggers it instead of adding a broader suppressing rule to ``.zizmor.yml``. +That keeps the exception local and visible during review. + +A typical line-level ignore looks like this: + +.. code-block:: yaml + + secrets: inherit # zizmor: ignore[secrets-inherit] - PTB cannot customize inherited secrets here yet. + +Use configuration rules in ``.zizmor.yml`` only when the finding is genuinely +project-wide. If you add a temporary rule while working through a batch of +findings, remove it again once the repository is clean. diff --git a/doc/user_guide/troubleshooting/index.rst b/doc/user_guide/troubleshooting/index.rst index 38cc5b545..b108fa6f9 100644 --- a/doc/user_guide/troubleshooting/index.rst +++ b/doc/user_guide/troubleshooting/index.rst @@ -17,6 +17,7 @@ proposed mitigations, some potentially specific to the related tool. format_check_reports_unmodified_files formatting_disable "F401 unused import" (reported by Ruff) + Ignoring Zizmor Findings ../features/metrics/ignore_findings debug_github_workflows From 1e8d7491f2cd225da75679f79edda9ecd320580b Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:36:32 +0200 Subject: [PATCH 3/7] Modify documentation structure and content to match PTB format --- doc/user_guide/configuration.rst | 1 + doc/user_guide/features/index.rst | 2 +- .../index.rst} | 28 ++++++------------- .../zizmor_configuration.rst | 15 ++++++++++ ...indings.rst => handle_zizmor_findings.rst} | 15 ++++++++-- doc/user_guide/troubleshooting/index.rst | 2 +- 6 files changed, 39 insertions(+), 24 deletions(-) rename doc/user_guide/features/{managing_dependencies.rst => managing_dependencies/index.rst} (71%) create mode 100644 doc/user_guide/features/managing_dependencies/zizmor_configuration.rst rename doc/user_guide/troubleshooting/{ignore_zizmor_findings.rst => handle_zizmor_findings.rst} (74%) diff --git a/doc/user_guide/configuration.rst b/doc/user_guide/configuration.rst index d2d33ea43..ffc5e4395 100644 --- a/doc/user_guide/configuration.rst +++ b/doc/user_guide/configuration.rst @@ -16,4 +16,5 @@ features: features/metrics/sonar Formatting + Zizmor features/github_workflows/github_project_configuration diff --git a/doc/user_guide/features/index.rst b/doc/user_guide/features/index.rst index bd98ae29e..373fb643b 100644 --- a/doc/user_guide/features/index.rst +++ b/doc/user_guide/features/index.rst @@ -10,7 +10,7 @@ Features github_workflows/index documentation/index creating_a_release - managing_dependencies + managing_dependencies/index git_hooks/index metrics/collecting_metrics diff --git a/doc/user_guide/features/managing_dependencies.rst b/doc/user_guide/features/managing_dependencies/index.rst similarity index 71% rename from doc/user_guide/features/managing_dependencies.rst rename to doc/user_guide/features/managing_dependencies/index.rst index 01d5e5632..3fa801155 100644 --- a/doc/user_guide/features/managing_dependencies.rst +++ b/doc/user_guide/features/managing_dependencies/index.rst @@ -1,6 +1,13 @@ +.. _managing_dependencies: + Managing Dependencies and Vulnerabilities ========================================= +.. toctree:: + :maxdepth: 1 + + zizmor_configuration + +------------------------------+----------------+-------------------------------------+ | Nox session | CI Usage | Action | +==============================+================+=====================================+ @@ -19,25 +26,6 @@ Managing Dependencies and Vulnerabilities | | | actions and workflows for security | | | | issues and accepts extra zizmor | | | | arguments. See | -| | | :ref:`zizmor_configuration` for | -| | | configuration details. | +| | | :ref:`zizmor_configuration`. | +------------------------------+----------------+-------------------------------------+ -.. _zizmor_configuration: - -Configuring Zizmor ------------------- - -``workflow:audit`` uses `zizmor `__ to audit GitHub -Actions and workflows. Zizmor reads its project configuration from a file named -``.zizmor.yml`` in the repository root. - -As a starting point, copy the template shipped with the PTB: - -.. literalinclude:: ../../../exasol/toolbox/templates/github/zizmor.yml - :language: yaml - -For details on the available audit and configuration options, see the -`zizmor documentation `__. - -For how to ignore accepted findings, see :ref:`ignore_zizmor_findings`. diff --git a/doc/user_guide/features/managing_dependencies/zizmor_configuration.rst b/doc/user_guide/features/managing_dependencies/zizmor_configuration.rst new file mode 100644 index 000000000..38e7240f8 --- /dev/null +++ b/doc/user_guide/features/managing_dependencies/zizmor_configuration.rst @@ -0,0 +1,15 @@ +.. _zizmor_configuration: + +Configuring Zizmor +================== + +``workflow:audit`` uses `zizmor `__ to audit GitHub +Actions and workflows. Zizmor reads its project configuration from a file named +``.zizmor.yml`` in the repository root. + +As a starting point, copy the template shipped with the PTB: + +.. literalinclude:: ../../../../exasol/toolbox/templates/github/zizmor.yml + :language: yaml + +For troubleshooting help, see :ref:`handle_zizmor_findings`. diff --git a/doc/user_guide/troubleshooting/ignore_zizmor_findings.rst b/doc/user_guide/troubleshooting/handle_zizmor_findings.rst similarity index 74% rename from doc/user_guide/troubleshooting/ignore_zizmor_findings.rst rename to doc/user_guide/troubleshooting/handle_zizmor_findings.rst index fbed3293d..69916e4fe 100644 --- a/doc/user_guide/troubleshooting/ignore_zizmor_findings.rst +++ b/doc/user_guide/troubleshooting/handle_zizmor_findings.rst @@ -1,8 +1,11 @@ -.. _ignore_zizmor_findings: +.. _handle_zizmor_findings: -Ignoring Zizmor Findings +Handling Zizmor Findings ======================== +Fixing the Issues +----------------- + `zizmor `__ can automatically fix some findings. The ``--fix`` flag accepts three modes: @@ -11,6 +14,14 @@ Ignoring Zizmor Findings correct but require human review because they can affect semantics. * ``--fix=all`` applies both safe and unsafe fixes. +If a finding does not have a known auto-fix, check the relevant audit +documentation in the `zizmor documentation `__. +That usually makes it clearer whether the issue needs a code change, a +configuration change, or an accepted exception. + +Ignoring Accepted Issues +------------------------ + When you are first enabling ``workflow:audit``, it can be practical to start with a broader ``.zizmor.yml`` configuration and then tighten it over time. However, once a finding is understood, prefer ignoring the specific line that diff --git a/doc/user_guide/troubleshooting/index.rst b/doc/user_guide/troubleshooting/index.rst index b108fa6f9..b963e1973 100644 --- a/doc/user_guide/troubleshooting/index.rst +++ b/doc/user_guide/troubleshooting/index.rst @@ -17,7 +17,7 @@ proposed mitigations, some potentially specific to the related tool. format_check_reports_unmodified_files formatting_disable "F401 unused import" (reported by Ruff) - Ignoring Zizmor Findings + Handling Zizmor Findings ../features/metrics/ignore_findings debug_github_workflows From fd4a73965a5ce6ea5df5e4493a5ae373fe01bcfb Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:42:27 +0200 Subject: [PATCH 4/7] Run format:fix --- exasol/toolbox/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exasol/toolbox/config.py b/exasol/toolbox/config.py index aabbe8a00..4e7211342 100644 --- a/exasol/toolbox/config.py +++ b/exasol/toolbox/config.py @@ -358,4 +358,4 @@ def zizmor_config_path(self) -> Path: """ Path where the zizmor configuration file for the project is stored. """ - return self.root_path / ".zizmor.yml" \ No newline at end of file + return self.root_path / ".zizmor.yml" From 1440173cc9741d3cf7efcc6bdcc782eb9bff1b9c Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:46:39 +0200 Subject: [PATCH 5/7] Fix table entry and reformat table to easier to manage form --- .../features/managing_dependencies/index.rst | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/user_guide/features/managing_dependencies/index.rst b/doc/user_guide/features/managing_dependencies/index.rst index 3fa801155..2502d6920 100644 --- a/doc/user_guide/features/managing_dependencies/index.rst +++ b/doc/user_guide/features/managing_dependencies/index.rst @@ -8,24 +8,24 @@ Managing Dependencies and Vulnerabilities zizmor_configuration -+------------------------------+----------------+-------------------------------------+ -| Nox session | CI Usage | Action | -+==============================+================+=====================================+ -| ``dependency:licenses`` | ``report.yml`` | Uses ``pip-licenses`` to return | -| | | packages with their licenses | -+------------------------------+----------------+-------------------------------------+ -| ``dependency:audit`` | No | Uses ``pip-audit`` to report active | -| | | vulnerabilities in our dependencies | -+------------------------------+----------------+-------------------------------------+ -| ``vulnerabilities:resolved`` | No | Uses ``pip-audit`` to report known | -| | | vulnerabilities in dependencies | -| | | that have been resolved in | -| | | comparison to the last release. | -+------------------------------+----------------+-------------------------------------+ -| ``workflow:audit`` | ``checks.yml`` | Uses ``zizmor`` to audit GitHub | -| | | actions and workflows for security | -| | | issues and accepts extra zizmor | -| | | arguments. See | -| | | :ref:`zizmor_configuration`. | -+------------------------------+----------------+-------------------------------------+ +.. list-table:: + :widths: 25 20 55 + :header-rows: 1 + * - Nox session + - CI Usage + - Action + * - ``dependency:licenses`` + - ``report.yml`` + - Uses ``pip-licenses`` to return packages with their licenses. + * - ``dependency:audit`` + - ``dependency-update.yml`` + - Uses ``pip-audit`` to report active vulnerabilities in our dependencies. + * - ``vulnerabilities:resolved`` + - No + - Uses ``pip-audit`` to report known vulnerabilities in dependencies that + have been resolved in comparison to the last release. + * - ``workflow:audit`` + - ``checks.yml`` + - Uses ``zizmor`` to audit GitHub actions and workflows for security issues + and accepts extra zizmor arguments. See :ref:`zizmor_configuration`. From a018847432038c4e5e480889826b37cb09c310be Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 10:49:28 +0200 Subject: [PATCH 6/7] Align names once more --- .github/workflows/checks.yml | 4 ++-- exasol/toolbox/templates/github/workflows/checks.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9a4aa271d..2c0dc355e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -247,6 +247,6 @@ jobs: python-version: "3.10" poetry-version: "2.3.0" - - name: Check Workflows - id: check-workflows + - name: Audit Workflows + id: audit-workflows run: poetry run -- nox -s workflow:audit diff --git a/exasol/toolbox/templates/github/workflows/checks.yml b/exasol/toolbox/templates/github/workflows/checks.yml index d78ad0456..ac3109f0b 100644 --- a/exasol/toolbox/templates/github/workflows/checks.yml +++ b/exasol/toolbox/templates/github/workflows/checks.yml @@ -246,6 +246,6 @@ jobs: python-version: "(( minimum_python_version ))" poetry-version: "(( dependency_manager_version ))" - - name: Check Workflows - id: check-workflows + - name: Audit Workflows + id: audit-workflows run: poetry run -- nox -s workflow:audit From 92f31214d63641bdbb66edc1e54e014fcbbcc06c Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Thu, 18 Jun 2026 11:42:11 +0200 Subject: [PATCH 7/7] Simplify and fix test to use a zizmor value --- test/unit/nox/_workflow_test.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/nox/_workflow_test.py b/test/unit/nox/_workflow_test.py index b6183c7ea..fad8a1013 100644 --- a/test/unit/nox/_workflow_test.py +++ b/test/unit/nox/_workflow_test.py @@ -152,7 +152,7 @@ class TestAuditWorkflows: @staticmethod @pytest.mark.parametrize( "nox_session_runner_posargs", - [["--config-file", "custom.yml", "--no-progress"]], + [["--version"]], indirect=["nox_session_runner_posargs"], ) def test_passes_through_extra_arguments( @@ -177,8 +177,6 @@ def test_passes_through_extra_arguments( "zizmor", "--config", config_path, - "--config-file", - "custom.yml", - "--no-progress", + "--version", project_config_without_patcher.root_path, )