From 08275875f5ec7b18f591523dcb565f46ca62a76a Mon Sep 17 00:00:00 2001 From: Marvin Friede <51965259+marvinfriede@users.noreply.github.com> Date: Sun, 15 Dec 2024 10:25:16 -0600 Subject: [PATCH] Fix zizmor security issues in GA (#32) --- .github/workflows/codeql.yaml | 67 ++++++++++++++++--------------- .github/workflows/macos-arm.yaml | 10 ++++- .github/workflows/macos-x86.yaml | 10 ++++- .github/workflows/release.yaml | 30 ++++++++++---- .github/workflows/ubuntu.yaml | 12 ++++-- .github/workflows/windows.yaml | 10 ++++- .pre-commit-config.yaml | 14 ++++++- src/tad_multicharge/model/base.py | 14 +++++-- src/tad_multicharge/model/eeq.py | 43 +++++++++++++------- 9 files changed, 142 insertions(+), 68 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index e280d22..5912558 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -13,11 +13,11 @@ name: "CodeQL" on: push: - branches: [ "main" ] + branches: ["main"] pull_request: - branches: [ "main" ] + branches: ["main"] schedule: - - cron: '31 23 * * 0' + - cron: "31 23 * * 0" jobs: analyze: @@ -37,45 +37,46 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'python' ] + language: ["python"] # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - queries: +security-and-quality + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + queries: +security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/macos-arm.yaml b/.github/workflows/macos-arm.yaml index 0a6ea41..4d4c23e 100644 --- a/.github/workflows/macos-arm.yaml +++ b/.github/workflows/macos-arm.yaml @@ -75,6 +75,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 @@ -90,7 +92,11 @@ jobs: run: echo "TOXENV=py$(echo ${{ matrix.python-version }} | tr -d '.')-torch$(echo ${{ matrix.torch-version }} | tr -d '.')" >> $GITHUB_ENV - name: Print TOXENV - run: echo "TOXENV is set to '${{ env.TOXENV }}'." + run: echo "TOXENV is set to '${TOXENV}'." + env: + TOXENV: ${{ env.TOXENV }} - name: Unittests with tox - run: tox -e ${{ env.TOXENV }} + run: tox -e $TOXENV + env: + TOXENV: ${{ env.TOXENV }} diff --git a/.github/workflows/macos-x86.yaml b/.github/workflows/macos-x86.yaml index f45d9da..5c4ccfa 100644 --- a/.github/workflows/macos-x86.yaml +++ b/.github/workflows/macos-x86.yaml @@ -86,6 +86,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 @@ -101,7 +103,11 @@ jobs: run: echo "TOXENV=py$(echo ${{ matrix.python-version }} | tr -d '.')-torch$(echo ${{ matrix.torch-version }} | tr -d '.')" >> $GITHUB_ENV - name: Print TOXENV - run: echo "TOXENV is set to '${{ env.TOXENV }}'." + run: echo "TOXENV is set to '${TOXENV}'." + env: + TOXENV: ${{ env.TOXENV }} - name: Unittests with tox - run: tox -e ${{ env.TOXENV }} + run: tox -e $TOXENV + env: + TOXENV: ${{ env.TOXENV }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6c0c94c..8371383 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -35,6 +35,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Build wheel (bdist) run: pipx run build --wheel @@ -49,6 +51,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Build source distribution (sdist) run: pipx run build --sdist @@ -58,9 +62,12 @@ jobs: with: path: dist/*.tar.gz - upload_pypi: - needs: [wheel, sdist] + upload_test_pypi: + needs: [sdist, wheel] runs-on: ubuntu-latest + environment: release + permissions: + id-token: write if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') steps: - name: Download build artifacts @@ -72,12 +79,21 @@ jobs: - name: Publish to Test PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - user: __token__ - password: ${{ secrets.TEST_PYPI_TOKEN }} repository-url: https://test.pypi.org/legacy/ + upload_pypi: + needs: [sdist, wheel, upload_test_pypi] + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + steps: + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: artifact + path: dist + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workflows/ubuntu.yaml b/.github/workflows/ubuntu.yaml index 810c4f7..e67d9f6 100644 --- a/.github/workflows/ubuntu.yaml +++ b/.github/workflows/ubuntu.yaml @@ -92,6 +92,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 @@ -107,13 +109,17 @@ jobs: run: echo "TOXENV=py$(echo ${{ matrix.python-version }} | tr -d '.')-torch$(echo ${{ matrix.torch-version }} | tr -d '.')" >> $GITHUB_ENV - name: Print TOXENV - run: echo "TOXENV is set to '${{ env.TOXENV }}'." + run: echo "TOXENV is set to '${TOXENV}'." + env: + TOXENV: ${{ env.TOXENV }} - name: Unittests with tox - run: tox -e ${{ env.TOXENV }} + run: tox -e $TOXENV + env: + TOXENV: ${{ env.TOXENV }} - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # 5.1.1 if: > matrix.python-version == '3.11' && matrix.torch-version == '2.2.2' && diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 5abf3d3..2c32980 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -84,6 +84,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 @@ -99,7 +101,11 @@ jobs: run: echo "TOXENV=py$(echo ${{ matrix.python-version }} | tr -d '.')-torch$(echo ${{ matrix.torch-version }} | tr -d '.')" >> $GITHUB_ENV - name: Print TOXENV - run: echo "TOXENV is set to '${{ env.TOXENV }}'." + run: echo "TOXENV is set to '${TOXENV}'." + env: + TOXENV: ${{ env.TOXENV }} - name: Unittests with tox - run: tox -e ${{ env.TOXENV }} + run: tox -e $TOXENV + env: + TOXENV: ${{ env.TOXENV }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 84f1dc1..b1ea886 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: --min-py-version, "3.8", --max-py-version, - "3.11", + "3.12", ] - repo: https://github.com/asottile/pyupgrade @@ -58,3 +58,15 @@ repos: hooks: - id: black stages: [pre-commit] + + - repo: https://github.com/woodruffw/zizmor-pre-commit + rev: v0.9.2 + hooks: + - id: zizmor + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.13.0 + hooks: + - id: mypy + pass_filenames: false + args: [--config-file=pyproject.toml, --ignore-missing-imports, src] diff --git a/src/tad_multicharge/model/base.py b/src/tad_multicharge/model/base.py index d8978ae..10c793e 100644 --- a/src/tad_multicharge/model/base.py +++ b/src/tad_multicharge/model/base.py @@ -84,7 +84,8 @@ def solve( positions: Tensor, total_charge: Tensor, cn: Tensor, - ) -> tuple[Tensor, Tensor]: + return_energy: bool = False, + ) -> Tensor | tuple[Tensor, Tensor]: """ Solve the electronegativity equilibration for the partial charges minimizing the electrostatic energy. @@ -93,17 +94,22 @@ def solve( ---------- numbers : Tensor Atomic numbers of all atoms in the system. + (shape: ``(..., nat)``). positions : Tensor - Cartesian coordinates of the atoms in the system (batch, natoms, 3). + Cartesian coordinates of the atoms in system + (shape: ``(..., nat, 3)``). total_charge : Tensor Total charge of the system. model : ChargeModel Charge model to use. cn : Tensor Coordination numbers for all atoms in the system. + return_energy : bool, optional + Return the EEQ energy as well. Defaults to `False`. Returns ------- - (Tensor, Tensor) - Tuple of electrostatic energies and partial charges. + Tensor | (Tensor, Tensor) + Tensor of electrostatic charges or tuple of partial charges and + electrostatic energies if ``return_energy=True``. """ diff --git a/src/tad_multicharge/model/eeq.py b/src/tad_multicharge/model/eeq.py index c5e9df9..6d26b94 100644 --- a/src/tad_multicharge/model/eeq.py +++ b/src/tad_multicharge/model/eeq.py @@ -57,7 +57,15 @@ from tad_mctc.ncoord import cn_eeq, erf_count from ..param import defaults, eeq2019 -from ..typing import DD, Any, CountingFunction, Tensor, get_default_dtype, overload +from ..typing import ( + DD, + Any, + CountingFunction, + Literal, + Tensor, + get_default_dtype, + overload, +) from .base import ChargeModel __all__ = ["EEQModel", "get_charges"] @@ -113,20 +121,20 @@ def solve( positions: Tensor, total_charge: Tensor, cn: Tensor, - return_energy: bool = False, + return_energy: Literal[False], ) -> Tensor: ... - @overload + @overload # type: ignore[no-redef] def solve( self, numbers: Tensor, positions: Tensor, total_charge: Tensor, cn: Tensor, - return_energy: bool = True, + return_energy: Literal[True], ) -> tuple[Tensor, Tensor]: ... - def solve( + def solve( # type: ignore[no-redef] self, numbers: Tensor, positions: Tensor, @@ -142,12 +150,12 @@ def solve( ---------- numbers : Tensor Atomic numbers of all atoms in the system. + (shape: ``(..., nat)``). positions : Tensor - Cartesian coordinates of the atoms in the system (batch, natoms, 3). + Cartesian coordinates of the atoms in system + (shape: ``(..., nat, 3)``). total_charge : Tensor Total charge of the system. - model : ChargeModel - Charge model to use. cn : Tensor Coordination numbers for all atoms in the system. return_energy : bool, optional @@ -288,12 +296,12 @@ def get_eeq( cutoff: Tensor | float | int | None = defaults.EEQ_CN_CUTOFF, cn_max: Tensor | float | int | None = defaults.EEQ_CN_MAX, kcn: Tensor | float | int = defaults.EEQ_KCN, - return_energy: bool = False, + return_energy: Literal[False], **kwargs: Any, ) -> Tensor: ... -@overload +@overload # type: ignore[no-redef] def get_eeq( numbers: Tensor, positions: Tensor, @@ -303,12 +311,13 @@ def get_eeq( rcov: Tensor | None = None, cutoff: Tensor | float | int | None = defaults.EEQ_CN_CUTOFF, cn_max: Tensor | float | int | None = defaults.EEQ_CN_MAX, - return_energy: bool = True, + kcn: Tensor | float | int = defaults.EEQ_KCN, + return_energy: Literal[True], **kwargs: Any, -) -> Tensor | tuple[Tensor, Tensor]: ... +) -> tuple[Tensor, Tensor]: ... -def get_eeq( +def get_eeq( # type: ignore[no-redef] numbers: Tensor, positions: Tensor, chrg: Tensor, @@ -419,4 +428,10 @@ def get_energy( Tensor Atomic energies. """ - return get_eeq(numbers, positions, chrg, cutoff=cutoff, return_energy=True)[1] + return get_eeq( + numbers, + positions, + chrg, + cutoff=cutoff, + return_energy=True, + )[1]