From 47f568b18f4320ba534b23982d40574738729a87 Mon Sep 17 00:00:00 2001 From: Keshava P Date: Fri, 9 Oct 2026 19:10:19 +0530 Subject: [PATCH] don't resolve the kernel's own connection file through the cwd --- ipykernel/connect.py | 4 +++- ipykernel/kernelapp.py | 6 ++++++ tests/test_kernelapp.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/ipykernel/connect.py b/ipykernel/connect.py index e93ffb90e..49360a464 100644 --- a/ipykernel/connect.py +++ b/ipykernel/connect.py @@ -34,7 +34,9 @@ def get_connection_file(app: IPKernelApp | None = None) -> str: raise RuntimeError(msg) app = IPKernelApp.instance() - return filefind(app.connection_file, [".", app.connection_dir]) + # The kernel's own file lives in connection_dir; the working directory is + # only a fallback for a relative name that was passed on the command line. + return filefind(app.connection_file, [app.connection_dir, "."]) def _find_connection_file(connection_file): diff --git a/ipykernel/kernelapp.py b/ipykernel/kernelapp.py index 1c36022e1..41ffbcc39 100644 --- a/ipykernel/kernelapp.py +++ b/ipykernel/kernelapp.py @@ -331,7 +331,13 @@ def cleanup_connection_file(self): def init_connection_file(self): """Initialize our connection file.""" if not self.connection_file: + # Nobody gave us a name, so this file is ours to create. Don't go + # looking for the name we just invented: a file carrying it in the + # working directory is not this kernel's connection info. self.connection_file = "kernel-%s.json" % os.getpid() + Path(self.abs_connection_file).parent.mkdir(mode=0o700, exist_ok=True, parents=True) + atexit.register(self.cleanup_connection_file) + return try: self.connection_file = filefind(self.connection_file, [".", self.connection_dir]) except OSError: diff --git a/tests/test_kernelapp.py b/tests/test_kernelapp.py index ff654f06f..44a06886a 100644 --- a/tests/test_kernelapp.py +++ b/tests/test_kernelapp.py @@ -10,6 +10,7 @@ from jupyter_core.paths import secure_write from traitlets.config.loader import Config +from ipykernel.connect import get_connection_file from ipykernel.kernelapp import IPKernelApp from .conftest import MockKernel @@ -181,3 +182,36 @@ def test_init_sockets_tcp_without_curve_logs_warning(): assert any("Kernel is running over TCP without encryption" in m for m in messages), ( "Expected a warning about missing encryption when transport=tcp without curve keys" ) + + +def test_default_connection_file_ignores_working_directory(): + planted = { + "ip": "127.0.0.1", + "transport": "tcp", + "signature_scheme": "hmac-sha256", + "key": "planted-key", + "shell_port": 51111, + "iopub_port": 51112, + "stdin_port": 51113, + "control_port": 51114, + "hb_port": 51115, + } + basename = "kernel-%s.json" % os.getpid() + with TemporaryWorkingDirectory() as d: + with open(os.path.join(d, basename), "w") as f: + json.dump(planted, f) + + app = IPKernelApp(connection_dir=os.path.join(d, "runtime")) + app.init_connection_file() + + # the kernel owns the file of that name in connection_dir and took + # nothing from the one sitting in the working directory + assert app.connection_file == basename + assert app.abs_connection_file == os.path.join(app.connection_dir, basename) + assert app.session.key != b"planted-key" + assert app.shell_port == 0 + + # and that is the file handed out to other clients + with open(app.abs_connection_file, "w") as f: + json.dump({"key": "real-key"}, f) + assert get_connection_file(app) == app.abs_connection_file