From 10ba12ef72929caff4a0b614c970cac67bdbd77b Mon Sep 17 00:00:00 2001 From: Vincent Roseberry Date: Thu, 29 Oct 2026 18:59:45 +0000 Subject: [PATCH 1/3] Upgrade base image to release-colab-external-images_20261027-060057_RC00 http://b/493600019 --- Dockerfile.tmpl | 15 ++------------- kaggle_requirements.txt | 4 ---- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/Dockerfile.tmpl b/Dockerfile.tmpl index e6beb37e..9637cbcf 100644 --- a/Dockerfile.tmpl +++ b/Dockerfile.tmpl @@ -1,7 +1,7 @@ {{ if eq .Accelerator "gpu" }} -FROM us-docker.pkg.dev/colab-images/public/runtime:release-colab-external-images_20260917-060051_RC00 +FROM us-docker.pkg.dev/colab-images/public/runtime:release-colab-external-images_20261027-060057_RC00 {{ else }} -FROM us-docker.pkg.dev/colab-images/public/cpu-runtime:release-colab-external-images_20260917-060051_RC00 +FROM us-docker.pkg.dev/colab-images/public/cpu-runtime:release-colab-external-images_20261027-060057_RC00 {{ end}} ADD kaggle_requirements.txt /kaggle_requirements.txt @@ -13,14 +13,6 @@ RUN pip freeze | grep -E 'tensorflow|keras|torch|jax' > /colab_requirements.txt RUN cat /colab_requirements.txt >> /requirements.txt RUN cat /kaggle_requirements.txt >> /requirements.txt -# GHSA-hq85-5cpj-mr62: uv < 0.13.4 vendors a CA bundle that trusts emSign intermediates with compromised keys. -# Upgrade it first so the patched uv performs all subsequent installs. -# The base image's uv may not be the pip-managed one, so point every uv on PATH at the new binary. -# TODO(b/576329498): Remove once base image ships with newer uv, pip and certifi packages. -RUN uv pip install --system --no-cache "uv>=0.13.4" && \ - NEW_UV="$(python -c 'import uv; print(uv.find_uv_bin())')" && \ - for old in $(which -a uv); do [ "$old" -ef "$NEW_UV" ] || ln -sf "$NEW_UV" "$old"; done - # Install Kaggle packages RUN uv pip install --system --no-cache -r /requirements.txt @@ -56,9 +48,6 @@ RUN uv pip install --system --no-cache "pycuda" # as described by Lionel Chan at http://stackoverflow.com/a/37426929/5881346 RUN sed -i "s/httpredir.debian.org/debian.uchicago.edu/" /etc/apt/sources.list && \ apt-get update --allow-releaseinfo-change && \ - # Debian's trixie-security ca-certificates 20250419+deb13u1 blocklists it in the system store. - # TODO(b/576329498): Remove upgrade to ca-certificates once the base image ships the newer version. - apt-get install --no-install-recommends -y --only-upgrade ca-certificates && \ # Needed by lightGBM (GPU build) # https://lightgbm.readthedocs.io/en/latest/GPU-Tutorial.html#build-lightgbm apt-get install -y build-essential unzip cmake libboost-dev libboost-system-dev libboost-filesystem-dev p7zip-full && \ diff --git a/kaggle_requirements.txt b/kaggle_requirements.txt index b325d320..56213f32 100644 --- a/kaggle_requirements.txt +++ b/kaggle_requirements.txt @@ -15,8 +15,6 @@ bayesian-optimization boto3 catboost category-encoders -# GHSA-6q48-6c7w-9gw2: older bundles trust emSign intermediates with compromised keys. -certifi>=2026.10.19 cesium comm cytoolz @@ -110,8 +108,6 @@ pdf2image # The base image ships pillow 11.3; pin up to a newer release. # Remove once the base image ships >=12.2 itself. pillow>=12.2 -# pip < 26.2.2 always loads its vendored certifi, so it needs the GHSA-6q48-6c7w-9gw2 fix separately. -pip>=26.2.2 plotly-express pudb pyLDAvis From e8d005ed6c5793fdebfdc825e325c1e600d34100 Mon Sep 17 00:00:00 2001 From: Vincent Roseberry Date: Thu, 29 Oct 2026 20:51:31 +0000 Subject: [PATCH 2/3] unpin protobuf, remove deprecate google-generativeai package --- Dockerfile.tmpl | 4 +- tests/test_google_generativeai_patch.py | 55 ------------------- ...test_google_generativeai_patch_disabled.py | 46 ---------------- 3 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 tests/test_google_generativeai_patch.py delete mode 100644 tests/test_google_generativeai_patch_disabled.py diff --git a/Dockerfile.tmpl b/Dockerfile.tmpl index 9637cbcf..5de9b369 100644 --- a/Dockerfile.tmpl +++ b/Dockerfile.tmpl @@ -25,11 +25,9 @@ RUN uv pip uninstall --system --no-cache google-cloud-bigquery-storage RUN uv pip install --no-build-isolation --no-cache --system "git+https://github.com/Kaggle/learntools" # b/404590350: Ray and torchtune have conflicting cli named `tune`. `ray` is not part of Colab's base image. Re-install `tune` to ensure the torchtune CLI is available by default. -# b/468367647: Unpin protobuf, version greater than v5.29.5 causes issues with numerous packages -# grpcio-tools must be installed here (not in kaggle_requirements.txt) to stay version-compatible with protobuf. # setuptools v82+ removed pkg_resources RUN uv pip install --system --force-reinstall --no-cache --no-deps torchtune -RUN uv pip install --system --force-reinstall --no-cache "protobuf==5.29.5" "grpcio-tools>=1.60.0" "setuptools>=70.0,<82" +RUN uv pip install --system --force-reinstall --no-cache "grpcio-tools>=1.60.0" "setuptools>=70.0,<82" # Adding non-package dependencies: ADD clean-layer.sh /tmp/clean-layer.sh diff --git a/tests/test_google_generativeai_patch.py b/tests/test_google_generativeai_patch.py deleted file mode 100644 index 87ac4ecd..00000000 --- a/tests/test_google_generativeai_patch.py +++ /dev/null @@ -1,55 +0,0 @@ -import json -import unittest -import threading - -from test.support.os_helper import EnvironmentVarGuard -from urllib.parse import urlparse - -from http.server import BaseHTTPRequestHandler, HTTPServer - -class HTTPHandler(BaseHTTPRequestHandler): - called = False - path = None - headers = {} - - def do_HEAD(self): - self.send_response(200) - - def do_GET(self): - HTTPHandler.path = self.path - HTTPHandler.headers = self.headers - HTTPHandler.called = True - self.send_response(200) - self.send_header("Content-type", "application/json") - self.end_headers() - -class TestGoogleGenerativeAiPatch(unittest.TestCase): - endpoint = "http://127.0.0.1:80" - - def test_proxy_enabled(self): - env = EnvironmentVarGuard() - secrets_token = "secrets_token" - proxy_token = "proxy_token" - env.set("KAGGLE_USER_SECRETS_TOKEN", secrets_token) - env.set("KAGGLE_DATA_PROXY_TOKEN", proxy_token) - env.set("KAGGLE_DATA_PROXY_URL", self.endpoint) - env.set("KAGGLE_GRPC_DATA_PROXY_URL", "http://127.0.0.1:50001") - env.set("KAGGLE_GOOGLE_GENERATIVE_AI_USE_REST_ONLY", "True") - server_address = urlparse(self.endpoint) - with env: - with HTTPServer((server_address.hostname, server_address.port), HTTPHandler) as httpd: - threading.Thread(target=httpd.serve_forever).start() - import google.generativeai as palm - api_key = "NotARealAPIKey" - palm.configure(api_key = api_key) - try: - for _ in palm.list_models(): - pass - except: - pass - httpd.shutdown() - self.assertTrue(HTTPHandler.called) - self.assertIn("/palmapi", HTTPHandler.path) - self.assertEqual(proxy_token, HTTPHandler.headers["x-kaggle-proxy-data"]) - self.assertEqual("Bearer {}".format(secrets_token), HTTPHandler.headers["x-kaggle-authorization"]) - self.assertEqual(api_key, HTTPHandler.headers["x-goog-api-key"]) diff --git a/tests/test_google_generativeai_patch_disabled.py b/tests/test_google_generativeai_patch_disabled.py deleted file mode 100644 index 2f34af21..00000000 --- a/tests/test_google_generativeai_patch_disabled.py +++ /dev/null @@ -1,46 +0,0 @@ -import json -import unittest -import threading - -from test.support.os_helper import EnvironmentVarGuard -from urllib.parse import urlparse - -from http.server import BaseHTTPRequestHandler, HTTPServer - -class HTTPHandler(BaseHTTPRequestHandler): - called = False - - def do_HEAD(self): - self.send_response(200) - - def do_GET(self): - print('YO MOD', self.path) - HTTPHandler.called = True - self.send_response(200) - self.send_header("Content-type", "application/json") - self.end_headers() - -class TestGoogleGenerativeAiPatchDisabled(unittest.TestCase): - http_endpoint = "http://127.0.0.1:80" - grpc_endpoint = "http://127.0.0.1:50001" - - def test_disabled(self): - env = EnvironmentVarGuard() - env.set("KAGGLE_USER_SECRETS_TOKEN", "foobar") - env.set("KAGGLE_DATA_PROXY_TOKEN", "foobar") - env.set("KAGGLE_DATA_PROXY_URL", self.http_endpoint) - env.set("KAGGLE_GRPC_DATA_PROXY_URL", self.grpc_endpoint) - env.set("KAGGLE_DISABLE_GOOGLE_GENERATIVE_AI_INTEGRATION", "True") - server_address = urlparse(self.http_endpoint) - with env: - with HTTPServer((server_address.hostname, server_address.port), HTTPHandler) as httpd: - threading.Thread(target=httpd.serve_forever).start() - import google.generativeai as palm - palm.configure(api_key = "NotARealAPIKey") - try: - for _ in palm.list_models(): - pass - except: - pass - httpd.shutdown() - self.assertFalse(HTTPHandler.called) From 128acf7b3bcb77e50b5febe120bb572e660c6a80 Mon Sep 17 00:00:00 2001 From: Vincent Roseberry Date: Fri, 30 Oct 2026 17:13:46 +0000 Subject: [PATCH 3/3] Remove google.generativeai patch --- patches/sitecustomize.py | 42 ---------------------------------------- 1 file changed, 42 deletions(-) diff --git a/patches/sitecustomize.py b/patches/sitecustomize.py index 1bb8a1b6..1e165063 100644 --- a/patches/sitecustomize.py +++ b/patches/sitecustomize.py @@ -73,48 +73,6 @@ def exec_module(self, module): if not hasattr(sys, 'frozen'): sys.meta_path.insert(0, GcpModuleFinder()) -@wrapt.when_imported('google.generativeai') -def post_import_logic(module): - if os.getenv('KAGGLE_DISABLE_GOOGLE_GENERATIVE_AI_INTEGRATION') != None: - return - if (os.getenv('KAGGLE_DATA_PROXY_TOKEN') == None or - os.getenv('KAGGLE_USER_SECRETS_TOKEN') == None or - (os.getenv('KAGGLE_DATA_PROXY_URL') == None and - os.getenv('KAGGLE_GRPC_DATA_PROXY_URL') == None)): - return - - old_configure = module.configure - - def new_configure(*args, **kwargs): - if ('default_metadata' in kwargs): - default_metadata = kwargs['default_metadata'] - else: - default_metadata = [] - default_metadata.append(("x-kaggle-proxy-data", os.environ['KAGGLE_DATA_PROXY_TOKEN'])) - user_secrets_token = os.environ['KAGGLE_USER_SECRETS_TOKEN'] - default_metadata.append(('x-kaggle-authorization', f'Bearer {user_secrets_token}')) - kwargs['default_metadata'] = default_metadata - - if ('client_options' in kwargs): - client_options = kwargs['client_options'] - else: - client_options = {} - - if os.getenv('KAGGLE_GOOGLE_GENERATIVE_AI_USE_REST_ONLY') != None: - kwargs['transport'] = 'rest' - - if 'transport' in kwargs and kwargs['transport'] == 'rest': - client_options['api_endpoint'] = os.environ['KAGGLE_DATA_PROXY_URL'] - client_options['api_endpoint'] += '/palmapi' - else: - client_options['api_endpoint'] = os.environ['KAGGLE_GRPC_DATA_PROXY_URL'] - kwargs['client_options'] = client_options - - old_configure(*args, **kwargs) - - module.configure = new_configure - module.configure() # generativeai can use GOOGLE_API_KEY env variable, so make sure we have the other configs set - @wrapt.when_imported('google.genai') def post_genai_import_logic(module): if os.getenv('KAGGLE_DISABLE_GOOGLE_GENERATIVE_AI_INTEGRATION'):