From adb9b0789a59917170cc526bd2104d2a282c63f9 Mon Sep 17 00:00:00 2001 From: tomas Date: Mon, 26 Oct 2026 14:00:47 +0000 Subject: [PATCH 1/4] fix(ci): run pip-audit for the server extra and the dev group The existing audit jobs export only the main dependencies, so packages that ship in the server extra (jupyter-server, streamlit and their dependencies) and the dev group are never audited. Add an audit job for each, sharing the existing ignore list. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HwkxN8YriHhdXBwMc4sd8h --- .github/workflows/ci.yml | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aca103a..7ca88b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -520,3 +520,77 @@ jobs: require-hashes: true disable-pip: true ignore-vulns: *ignore-vulns + + audit-server: + name: Audit - Server + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + with: + persist-credentials: false + + - name: Set up Python + id: setup-python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: '3.11' + + - name: Install Poetry + uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 + with: + version: ${{ env.POETRY_VERSION }} + virtualenvs-create: ${{ env.POETRY_VIRTUALENVS_CREATE }} + virtualenvs-in-project: ${{ env.POETRY_VIRTUALENVS_IN_PROJECT }} + installer-parallel: ${{ env.POETRY_INSTALLER_PARALLEL }} + + - name: Install poetry-plugin-export + run: poetry self add poetry-plugin-export + + - name: Run audit for server extra dependencies + run: | + poetry export --extras server -f requirements.txt -o /tmp/requirements-server.txt + + - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) + with: + inputs: /tmp/requirements-server.txt + require-hashes: true + disable-pip: true + ignore-vulns: *ignore-vulns + + audit-dev: + name: Audit - Dev + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + with: + persist-credentials: false + + - name: Set up Python + id: setup-python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: '3.11' + + - name: Install Poetry + uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 + with: + version: ${{ env.POETRY_VERSION }} + virtualenvs-create: ${{ env.POETRY_VIRTUALENVS_CREATE }} + virtualenvs-in-project: ${{ env.POETRY_VIRTUALENVS_IN_PROJECT }} + installer-parallel: ${{ env.POETRY_INSTALLER_PARALLEL }} + + - name: Install poetry-plugin-export + run: poetry self add poetry-plugin-export + + - name: Run audit for dev dependencies + run: | + poetry export --only dev -f requirements.txt -o /tmp/requirements-dev.txt + + - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) + with: + inputs: /tmp/requirements-dev.txt + require-hashes: true + disable-pip: true + ignore-vulns: *ignore-vulns From a9f611de096c4e1b6fb9e107aaf3dda1da8cb428 Mon Sep 17 00:00:00 2001 From: tomas Date: Mon, 26 Oct 2026 18:13:48 +0000 Subject: [PATCH 2/4] fix(deps): resolve pip-audit findings in the server extra and dev group - jupyter-server 2.21.0 fixes PYSEC-2026-4054 (token from the Referer logged in plain text on 500 errors). - anyio floor of 4.14.2 in the server extra fixes PYSEC-2026-4024 and PYSEC-2026-4025; anyio only reaches users through that extra. - pyspark 3.5.8 fixes PYSEC-2026-3966 in both the dev and license-check groups. - virtualenv 21.14.13 fixes its 19 advisories on Python >= 3.11. It needs filelock >= 3.24.2, and filelock 3.20.4 through 4.2.0 carry CVE-2026-112907/-112913/-112940, so filelock moves to 4.2.1+ and snowflake-connector-python to 4.8.1, the first release that allows filelock 4. Both require Python 3.11, so 3.10 keeps virtualenv 20.36.1, filelock 3.20.3 and snowflake-connector-python 4.8.0. On Python >= 3.11 this also moves packaging to 26.3 and platformdirs to 4.13.5 (required by virtualenv 21), and typing-extensions to 4.16.0 everywhere (required by anyio 4.15). Only the affected poetry.lock entries were spliced in. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HwkxN8YriHhdXBwMc4sd8h --- poetry.lock | 215 +++++++++++++++++++++++++++++++++++++++---------- pyproject.toml | 16 ++-- 2 files changed, 181 insertions(+), 50 deletions(-) diff --git a/poetry.lock b/poetry.lock index ef5df17..3a0d41e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -60,27 +60,24 @@ files = [ [[package]] name = "anyio" -version = "4.4.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" +version = "4.15.1" +description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = true -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main"] markers = "extra == \"server\"" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101"}, + {file = "anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} +typing_extensions = {version = ">=4.16.0", markers = "python_version < \"3.15\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] -trio = ["trio (>=0.23)"] +trio = ["trio (>=0.32.0)"] [[package]] name = "appnope" @@ -1919,11 +1916,25 @@ description = "Distribution utilities" optional = false python-versions = "*" groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] +[[package]] +name = "distlib" +version = "0.4.4" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "distlib-0.4.4-py2.py3-none-any.whl", hash = "sha256:cf09d55b1e85a89576b036aeb71550bfd68320f3f21761ca329eadadad918638"}, + {file = "distlib-0.4.4.tar.gz", hash = "sha256:ca4175b4ac7f71223cc30ed7248c45d2b38c2439d8ee6e498ab67ed63cf3508d"}, +] + [[package]] name = "dnspython" version = "2.8.0" @@ -2157,11 +2168,25 @@ description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["main", "dev"] +markers = "python_version == \"3.10\"" files = [ {file = "filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1"}, {file = "filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1"}, ] +[[package]] +name = "filelock" +version = "4.2.4" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.11" +groups = ["main", "dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "filelock-4.2.4-py3-none-any.whl", hash = "sha256:301241438c57936ef93f4243a94f2559022268bfcf9b375a9a72eb0f8db8358e"}, + {file = "filelock-4.2.4.tar.gz", hash = "sha256:c6d8663535e1650ee430507b4ffbac7b464dd64b7647ea0112a9f406499d163d"}, +] + [[package]] name = "flake8" version = "7.1.1" @@ -3359,15 +3384,15 @@ dev = ["autopep8", "black", "flake8", "mock", "pytest", "pytest-cov (>=2.6.1)"] [[package]] name = "jupyter-server" -version = "2.20.0" +version = "2.21.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"server\"" files = [ - {file = "jupyter_server-2.20.0-py3-none-any.whl", hash = "sha256:c3b67c93c471e947c18b5026f04f21614218adb706df8f48227d3ee8e0a7cdcc"}, - {file = "jupyter_server-2.20.0.tar.gz", hash = "sha256:b5778ba337d8015a3dc2b80803ecdd5ac18d3797fddf61a50ea5fb472b4ebe14"}, + {file = "jupyter_server-2.21.0-py3-none-any.whl", hash = "sha256:2ae2e5ce5e97268553e25aebe040197455673d925b5fc7995477153318160cf7"}, + {file = "jupyter_server-2.21.0.tar.gz", hash = "sha256:70d9a1883f57d3576ea17f4ce061ec1a7aad7ef388d00428cfb7f5e4f0022271"}, ] [package.dependencies] @@ -4349,11 +4374,25 @@ description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" groups = ["main", "dev", "license-check"] +markers = "python_version == \"3.10\"" files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "packaging" +version = "26.3" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev", "license-check"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, + {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, +] + [[package]] name = "pandas" version = "2.1.4" @@ -4961,6 +5000,7 @@ description = "A small Python package for determining appropriate platform-speci optional = false python-versions = ">=3.8" groups = ["main", "dev"] +markers = "python_version == \"3.10\"" files = [ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, @@ -4971,6 +5011,19 @@ docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx- test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] type = ["mypy (>=1.8)"] +[[package]] +name = "platformdirs" +version = "4.13.5" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.11" +groups = ["main", "dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "platformdirs-4.13.5-py3-none-any.whl", hash = "sha256:53d3ec4280b815c1e0b02edad7f9ee8fda1ba9c0865dd9c2e6e63849ce82fc1e"}, + {file = "platformdirs-4.13.5.tar.gz", hash = "sha256:05831adf87d392760f4b5c3a0a95579ab5a10b18b9b9bd43680dcb47544788a0"}, +] + [[package]] name = "pluggy" version = "1.5.0" @@ -6404,18 +6457,18 @@ certifi = "*" [[package]] name = "pyspark" -version = "3.5.5" +version = "3.5.9" description = "Apache Spark Python API" optional = false python-versions = ">=3.8" groups = ["dev", "license-check"] markers = "python_version <= \"3.12\"" files = [ - {file = "pyspark-3.5.5.tar.gz", hash = "sha256:6effc9ce98edf231f4d683fd14f7270629bf8458c628d6a2620ded4bb34f3cb9"}, + {file = "pyspark-3.5.9.tar.gz", hash = "sha256:ea27adc39ddac9413b8951e45aa748cbed6c785971b81386efc41938f6243d93"}, ] [package.dependencies] -py4j = "0.10.9.7" +py4j = ">=0.10.9.7,<0.10.9.10" [package.extras] connect = ["googleapis-common-protos (>=1.56.4)", "grpcio (>=1.56.0)", "grpcio-status (>=1.56.0)", "numpy (>=1.15,<2)", "pandas (>=1.0.5)", "pyarrow (>=4.0.0)"] @@ -6544,6 +6597,22 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-discovery" +version = "1.6.4" +description = "Python interpreter discovery" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "python_discovery-1.6.4-py3-none-any.whl", hash = "sha256:530179cc51a1816d512b15635b3dc931295ae12efb183783ad31190a5d425d2b"}, + {file = "python_discovery-1.6.4.tar.gz", hash = "sha256:bc70d31f0ec5de11eda13d4d64c16e24b3506a65984684f2b6c98cb83b2ea9df"}, +] + +[package.dependencies] +filelock = ">=3.16.1" + [[package]] name = "python-dotenv" version = "1.2.2" @@ -7730,19 +7799,6 @@ files = [ {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - [[package]] name = "snowflake-connector-python" version = "4.8.0" @@ -7750,6 +7806,7 @@ description = "Snowflake Connector for Python" optional = false python-versions = ">=3.10" groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "snowflake_connector_python-4.8.0-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:5ac7214337e2ca4797a63b12e2d6778b85b95bacbb1e8892e8ef5cdb2696bcdb"}, {file = "snowflake_connector_python-4.8.0-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:e3de20df18a0279cc913ecd073b79eae860fa00e3d0e8cb9cfb276ecf85fe319"}, @@ -7810,6 +7867,69 @@ development = ["Cython (>=3.1)", "azure-identity (>=1.16)", "coverage", "mitmpro pandas = ["pandas (>=1.0.0,<3.0.0) ; python_version < \"3.13\"", "pandas (>=2.1.2,<3.0.0) ; python_version >= \"3.13\"", "pyarrow (>=14.0.1) ; python_version < \"3.14\"", "pyarrow (>=14.0.1,<24) ; python_version >= \"3.14\""] secure-local-storage = ["keyring (>=23.1.0,<26.0.0)"] +[[package]] +name = "snowflake-connector-python" +version = "4.8.1" +description = "Snowflake Connector for Python" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "snowflake_connector_python-4.8.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:16b5f58134fc795955db0a3bf550dd07df691435fb1e7208a9220e7839ec9719"}, + {file = "snowflake_connector_python-4.8.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:315bf08c92fc15c4550643132373c995321743f45650dba9b65db60da169afe9"}, + {file = "snowflake_connector_python-4.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3a90c5d91b11e65a6185ae4878bbe1a85b2254ca78535a1a4703c67001aa48d1"}, + {file = "snowflake_connector_python-4.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c92a2e0618517dcf7a89296c329e2463401cb7a7740b9233d532d9a94ef47785"}, + {file = "snowflake_connector_python-4.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:137ffbcd74e09b5bb4533266a23467660a68ed97922e384376474485e766c47d"}, + {file = "snowflake_connector_python-4.8.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1f709334cb6ae2632dc9aea11041bd35fd57851182bca40ef64f24103fc1d97f"}, + {file = "snowflake_connector_python-4.8.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:d8c9cda50255e813d5b70e813e21d0d1358c6acb2d52f9a956b941471e254e7b"}, + {file = "snowflake_connector_python-4.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:28a0af61cb5ca0e49e90392d9b1e16ecf3fa359a9252d0f334c34939f17a71b2"}, + {file = "snowflake_connector_python-4.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d8178d9e90c8dc008cd3514dfc89adb4f80a49e85820de51175df72fd3772b6"}, + {file = "snowflake_connector_python-4.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:94a1ec863c27dc091ad3e9f7ee77ce3c6c25222dde4fcabc32384c5cd9d28ac7"}, + {file = "snowflake_connector_python-4.8.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:23e3d374cc8f6e6adb9a68fa5510b9e1b09ca0d264d9a2f80472e2a8d9383749"}, + {file = "snowflake_connector_python-4.8.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8155576e1f5489b88dff01cbb8f656f8e32833112c239d716c947cfe99233cab"}, + {file = "snowflake_connector_python-4.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90e73ddd4f3481089e37f8fd9c3269215a2de9c29bd050a83596d1c4eb2c763c"}, + {file = "snowflake_connector_python-4.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:42705a96dcd1e9c6cdc60faeb6d9f90f207abc7d0697f78635c4a7b95d5605d1"}, + {file = "snowflake_connector_python-4.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:4237f74b0265e2266ff50c9ebb5a7b45cc94d929111682e18ce04de11b6157fc"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:cf5872b8a0b5b394adea0bf233e13f21e9061c4ccf82e6165b1742cb44689a11"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:a668c2b98929281c23eb8d382ad5b141424adaf1b5e2b69ef3ec063aeb55f94f"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d28227747e768c76f6148f6853b502de17bffe09711dc6a3da21cd0e7712331c"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72cec25f38def137000f4930e99adbd8b5af99a92dad7b4d9d7ffce988cc75e4"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:20efe486609f98cd96a1da2ce5d8519866aaf9d42549f4103421d99eef13b344"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:39cd08312293c2b116c91e530bcc8e9ffd977afb90f04b718f7e7d7ae85b2f8b"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:d29a14bbd2ec7d395fcd619b7af9be4e920eb6bd70b409a176e940e9ee7c552e"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:529a7addbe45aa42ef05c2d49bc5a4182c087d85f7d42c837c673329dc6693ac"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:24e0f1a0d45434a076e563883df0331ebe3e19d038249833498f2d41b9877671"}, + {file = "snowflake_connector_python-4.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:b4d31d0e47fb5ceace4fd3b963f5d604b463e034da8bf5e6bd985680596d054d"}, + {file = "snowflake_connector_python-4.8.1.tar.gz", hash = "sha256:ff1ce7ef2aa476b2346be8e77218ddd6c58278354798cd89fb151c655dbd110d"}, +] + +[package.dependencies] +asn1crypto = ">0.24.0,<2.0.0" +boto3 = ">=1.24" +botocore = ">=1.24" +certifi = ">=2026.10.18" +charset_normalizer = ">=2,<4" +cryptography = ">=46.0.5" +filelock = ">=3.12,<5" +idna = ">=3.7,<4" +packaging = "*" +platformdirs = ">=2.6.0,<5.0.0" +pyjwt = ">=2.10.1,<3.0.0" +pyOpenSSL = ">=25.3.0" +pytz = "*" +requests = ">=2.32.4,<3.0.0" +sortedcontainers = ">=2.4.0" +tomlkit = "*" +typing_extensions = ">=4.3,<5" + +[package.extras] +azure = ["azure-identity (>=1.16)"] +boto = ["boto3 (>=1.24)", "botocore (>=1.24)"] +development = ["Cython (>=3.1)", "azure-identity (>=1.16)", "coverage", "mitmproxy (>=12.0.0) ; python_version >= \"3.12\" and python_version < \"3.14\"", "more-itertools", "numpy (<=2.4.3)", "pendulum (!=2.1.1)", "pexpect", "pytest (>=8.4,<9)", "pytest-asyncio (>=1.4.0,<2)", "pytest-cov", "pytest-rerunfailures (<16.0)", "pytest-timeout", "pytest-xdist", "pytzdata", "responses"] +pandas = ["pandas (>=1.0.0,<3.0.0) ; python_version < \"3.13\"", "pandas (>=2.1.2,<3.0.0) ; python_version >= \"3.13\"", "pyarrow (>=14.0.1) ; python_version < \"3.14\"", "pyarrow (>=14.0.1,<24) ; python_version >= \"3.14\""] +secure-local-storage = ["keyring (>=23.1.0,<26.0.0)"] + [[package]] name = "snowflake-sqlalchemy" version = "1.11.1" @@ -8557,19 +8677,6 @@ files = [ {file = "types_python_dateutil-2.9.0.20240821-py3-none-any.whl", hash = "sha256:f5889fcb4e63ed4aaa379b44f93c32593d50b9a94c9a60a0c854d8cc3511cd57"}, ] -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version < \"3.14\"" -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - [[package]] name = "typing-extensions" version = "4.16.0" @@ -8577,7 +8684,6 @@ description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main", "dev"] -markers = "python_version == \"3.14\"" files = [ {file = "typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8"}, {file = "typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5"}, @@ -8809,6 +8915,7 @@ description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f"}, {file = "virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba"}, @@ -8824,6 +8931,26 @@ typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\"" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] +[[package]] +name = "virtualenv" +version = "21.14.13" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "virtualenv-21.14.13-py3-none-any.whl", hash = "sha256:5fbb04138a4861580b78ba9110d529a26bc48fcc93c8ec36bc0202eeed96a788"}, + {file = "virtualenv-21.14.13.tar.gz", hash = "sha256:de5307ba4b9a0001d9c8ea02832d38f63ca432880f416c1bface61c4323fd905"}, +] + +[package.dependencies] +distlib = ">=0.4.3,<1" +filelock = {version = ">=3.24.2,<5", markers = "python_version >= \"3.10\""} +packaging = ">=26.3" +platformdirs = ">=4.4,<5" +python-discovery = ">=1.6.1" + [[package]] name = "vl-convert-python" version = "1.7.0" @@ -9458,4 +9585,4 @@ server = ["deepnote-python-lsp-server", "jupyter-resource-usage", "jupyter-serve [metadata] lock-version = "2.1" python-versions = ">=3.10.0,<3.15" -content-hash = "04a325f38a272beccf64959c3054ef9764fcbc230fcf8f2c6ce1aa57e94977aa" +content-hash = "6a0c5f79a475158d6dad0c41657ad78664e1b9f2f89449f7c92471c29f911f01" diff --git a/pyproject.toml b/pyproject.toml index 636e11e..8c49894 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,7 +93,8 @@ dependencies = [ "sqlalchemy<2; python_version <= '3.11'", "sqlalchemy>=2.0.45,<3; python_version >= '3.12'", "snowflake-sqlalchemy>=1.11.0,<2", # 1.11.0 fixes PYSEC-2026-3921 (SQL injection, local file read) - "snowflake-connector-python>=4.7.3,<5", # 4.7.3 fixes CVE-2026-86597 + "snowflake-connector-python>=4.8.1,<5; python_version >= '3.11'", # first release that allows filelock 4 + "snowflake-connector-python>=4.7.3,<5; python_version < '3.11'", # 4.7.3 fixes CVE-2026-86597 "sqlalchemy-spanner>=1.6.2,<2", "clickhouse-sqlalchemy>0,<0.4", "sqlalchemy-bigquery>1.6.1,<1.13; python_version < '3.13'", @@ -142,7 +143,8 @@ dependencies = [ "protobuf>=5.29.6,<6", "requests>=2.32.4,<3", "tornado>=6.5.9,<7", # 6.5.9 fixes GHSA-3hv7-mjh2-fv65, GHSA-c2m8-h5v5-343r, GHSA-chx6-46f5-w4vp - "filelock>=3.20.3,<4", + "filelock>=4.2.1,<5; python_version >= '3.11'", # 4.2.1 fixes CVE-2026-112907, CVE-2026-112913, CVE-2026-112940 + "filelock==3.20.3; python_version < '3.11'", # 3.20.4 through 4.2.0 carry those advisories, and 4.2.1 requires Python 3.11 "pyjwt>=2.15.0,<3", # 2.15.0 fixes PYSEC-2026-4140..4152, PYSEC-2026-4183 "fsspec>=2026.6.0", # 2026.6.0 fixes CVE-2026-104851 (transitive via pyathena) "certifi>=2026.10.19", # 2026.10.19 fixes PYSEC-2026-4320 (transitive via requests) @@ -184,7 +186,7 @@ Issues = "https://github.com/deepnote/deepnote-toolkit/issues" [project.optional-dependencies] server = [ - "jupyter-server==2.20.0", + "jupyter-server==2.21.0", # 2.21.0 fixes PYSEC-2026-4054 "jupyter-server-terminals==0.5.3", "jupyter-resource-usage>=1.1.0,<2.0.0", "streamlit>=1.66.1,<2.0.0; python_version >= '3.11'", # first release that allows pillow 13 @@ -192,6 +194,7 @@ server = [ "deepnote-python-lsp-server==1.13.1.1", "parso>=0.8.5,<0.9; python_version >= '3.14'", "pywinpty>=3.0.1; python_version >= '3.14' and sys_platform == 'win32'", + "anyio>=4.14.2,<5", # 4.14.2 fixes PYSEC-2026-4024, PYSEC-2026-4025 (transitive via jupyter-server) # Config dependencies - they need to be declared both in main and server extras, keep them in sync "pydantic>=1.10.0,<3; python_version < '3.13'", @@ -232,14 +235,15 @@ dev = [ # We do not distribute PySpark for all users because it's huge dependency (300mb) and not all # users need it. So in code we get pyspark from global module cache (since user already imported it at # that point). But we also have it as dev dependency to provide better autocompletion and for tests - "pyspark>=3.5.5,<4.0.0; python_version < '3.13'", + "pyspark>=3.5.8,<4.0.0; python_version < '3.13'", "pyspark>=4.0.0,<5.0.0; python_version == '3.13'", "pyspark>=4.1.0,<5.0.0; python_version >= '3.14'", "pyogrio>=0.12.0; python_version >= '3.14'", "pyproj>=3.7.2; python_version >= '3.14'", "shapely>=2.1.2; python_version >= '3.14'", "nox>=2025.11.12,<2026.0.0", - "virtualenv>=20.36.1", + "virtualenv>=21.14.13; python_version >= '3.11'", + "virtualenv>=20.36.1,<21; python_version < '3.11'", "poetry-dynamic-versioning>=1.4.0,<2.0.0", "twine>=6.1.0,<7.0.0", "codespell>=2.3.0,<3.0.0", @@ -251,7 +255,7 @@ license-check = [ # Dependencies needed for license checking that aren't in main production dependencies "geopandas>=1.1.2,<2; python_version < '3.12'", "geopandas>=1.1.2,<2; python_version >= '3.12'", - "pyspark>=3.5.5,<4.0.0; python_version < '3.13'", + "pyspark>=3.5.8,<4.0.0; python_version < '3.13'", "pyspark>=4.0.0,<5.0.0; python_version == '3.13'", "pyspark>=4.1.0,<5.0.0; python_version >= '3.14'", "pyogrio>=0.12.0; python_version >= '3.14'", From e71e3ed13d3ab9e6bf6e7302c152ff8eb062dd66 Mon Sep 17 00:00:00 2001 From: tomas Date: Mon, 26 Oct 2026 21:05:10 +0000 Subject: [PATCH 3/4] fix(ci): limit the new audit jobs' token to read-only contents Without a permissions block, Audit - Server and Audit - Dev inherited the repository's default GITHUB_TOKEN, which is write on nearly every scope. Both jobs only check out the repo and audit exported requirements, so contents: read is enough. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HwkxN8YriHhdXBwMc4sd8h --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ca88b0..d185db5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -525,6 +525,8 @@ jobs: name: Audit - Server runs-on: ubuntu-latest timeout-minutes: 3 + permissions: + contents: read steps: - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 with: @@ -562,6 +564,8 @@ jobs: name: Audit - Dev runs-on: ubuntu-latest timeout-minutes: 3 + permissions: + contents: read steps: - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 with: From 4d39d5916bbb556bb56226c4da3ab8a2e99a5e37 Mon Sep 17 00:00:00 2001 From: tomas Date: Tue, 27 Oct 2026 09:50:11 +0000 Subject: [PATCH 4/4] refactor(ci): run the pip-audit jobs as one matrix job Audit - Production, Audit - Server and Audit - Dev differed only in their poetry export flags, so they are now entries of one matrix job. The job name keeps each check's name, including the required Audit - Production. Audit - All is dropped because plain `poetry export` writes the same file as `--without dev`. With a single pip-audit step, the ignore list no longer needs a YAML anchor. The Production entry now also gets a read-only token. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HwkxN8YriHhdXBwMc4sd8h --- .github/workflows/ci.yml | 139 +++++---------------------------------- 1 file changed, 18 insertions(+), 121 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d185db5..9caef4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -433,10 +433,22 @@ jobs: path: coverage-data/coverage.xml retention-days: 30 - audit-prod: - name: Audit - Production + audit: + name: Audit - ${{ matrix.name }} runs-on: ubuntu-latest timeout-minutes: 3 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + include: + - name: Production + export-args: --without dev + - name: Server + export-args: --extras server + - name: Dev + export-args: --only dev steps: - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 with: @@ -459,13 +471,13 @@ jobs: - name: Install poetry-plugin-export run: poetry self add poetry-plugin-export - - name: Run audit for production dependencies + - name: Export dependencies run: | - poetry export --without dev -f requirements.txt -o /tmp/requirements-prod.txt + poetry export ${{ matrix.export-args }} -f requirements.txt -o /tmp/requirements.txt - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) with: - inputs: /tmp/requirements-prod.txt + inputs: /tmp/requirements.txt require-hashes: true disable-pip: true # PYSEC-2024-161 (pyarrow deserialization vulnerability) @@ -479,122 +491,7 @@ jobs: # PYSEC-2026-4114 (oauthlib PKCE code_verifier timing side-channel) # * not exploitable here: affects server-side AuthorizationCodeGrant validation; databricks-sql-connector only uses the client side (WebApplicationClient) # * fix is in oauthlib 4.0.0, but databricks-sql-connector (latest 4.6.0) caps oauthlib<4.0.0 - ignore-vulns: &ignore-vulns | + ignore-vulns: | PYSEC-2024-161 PYSEC-2026-113 PYSEC-2026-4114 - - audit-all: - name: Audit - All - runs-on: ubuntu-latest - timeout-minutes: 3 - steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 - with: - persist-credentials: false - - - name: Set up Python - id: setup-python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: '3.11' - - - name: Install Poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: ${{ env.POETRY_VIRTUALENVS_CREATE }} - virtualenvs-in-project: ${{ env.POETRY_VIRTUALENVS_IN_PROJECT }} - installer-parallel: ${{ env.POETRY_INSTALLER_PARALLEL }} - - - name: Install poetry-plugin-export - run: poetry self add poetry-plugin-export - - - name: Run audit for all dependencies - run: | - poetry export -f requirements.txt -o /tmp/requirements-all.txt - - - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) - with: - inputs: /tmp/requirements-all.txt - require-hashes: true - disable-pip: true - ignore-vulns: *ignore-vulns - - audit-server: - name: Audit - Server - runs-on: ubuntu-latest - timeout-minutes: 3 - permissions: - contents: read - steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 - with: - persist-credentials: false - - - name: Set up Python - id: setup-python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: '3.11' - - - name: Install Poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: ${{ env.POETRY_VIRTUALENVS_CREATE }} - virtualenvs-in-project: ${{ env.POETRY_VIRTUALENVS_IN_PROJECT }} - installer-parallel: ${{ env.POETRY_INSTALLER_PARALLEL }} - - - name: Install poetry-plugin-export - run: poetry self add poetry-plugin-export - - - name: Run audit for server extra dependencies - run: | - poetry export --extras server -f requirements.txt -o /tmp/requirements-server.txt - - - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) - with: - inputs: /tmp/requirements-server.txt - require-hashes: true - disable-pip: true - ignore-vulns: *ignore-vulns - - audit-dev: - name: Audit - Dev - runs-on: ubuntu-latest - timeout-minutes: 3 - permissions: - contents: read - steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 - with: - persist-credentials: false - - - name: Set up Python - id: setup-python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: '3.11' - - - name: Install Poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: ${{ env.POETRY_VIRTUALENVS_CREATE }} - virtualenvs-in-project: ${{ env.POETRY_VIRTUALENVS_IN_PROJECT }} - installer-parallel: ${{ env.POETRY_INSTALLER_PARALLEL }} - - - name: Install poetry-plugin-export - run: poetry self add poetry-plugin-export - - - name: Run audit for dev dependencies - run: | - poetry export --only dev -f requirements.txt -o /tmp/requirements-dev.txt - - - uses: pypa/gh-action-pip-audit@f1c3022531130da3984dbdfb2786f6e1cba15556 # latest release (v1.1.0 doesn't contain `disable-pip`) - with: - inputs: /tmp/requirements-dev.txt - require-hashes: true - disable-pip: true - ignore-vulns: *ignore-vulns