Package: ipython / 7.20.0-1+deb11u1

0004-Merge-pull-request-from-GHSA-pq7m-3gw7-gq5x.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
From: Matthias Bussonnier <bussonniermatthias@gmail.com>
Date: Wed, 19 Jan 2022 14:21:24 +0100
Subject: Merge pull request from GHSA-pq7m-3gw7-gq5x

FIX CVE-2022-21699
---
 IPython/__init__.py         |  4 ++++
 IPython/core/application.py |  2 +-
 IPython/core/profileapp.py  |  7 +++---
 IPython/core/profiledir.py  |  4 ++--
 IPython/tests/cve.py        | 56 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 67 insertions(+), 6 deletions(-)
 create mode 100644 IPython/tests/cve.py

diff --git a/IPython/__init__.py b/IPython/__init__.py
index 4fb7710..c17ec76 100644
--- a/IPython/__init__.py
+++ b/IPython/__init__.py
@@ -65,6 +65,10 @@
 __license__  = release.license
 __version__  = release.version
 version_info = release.version_info
+# list of CVEs that should have been patched in this release.
+# this is informational and should not be relied upon.
+__patched_cves__ = {"CVE-2022-21699"}
+
 
 def embed_kernel(module=None, local_ns=None, **kwargs):
     """Embed and start an IPython kernel in a given scope.
diff --git a/IPython/core/application.py b/IPython/core/application.py
index 93639d8..4f679df 100644
--- a/IPython/core/application.py
+++ b/IPython/core/application.py
@@ -133,7 +133,7 @@ def _config_file_name_changed(self, change):
     config_file_paths = List(Unicode())
     @default('config_file_paths')
     def _config_file_paths_default(self):
-        return [os.getcwd()]
+        return []
 
     extra_config_file = Unicode(
     help="""Path to an extra config file to load.
diff --git a/IPython/core/profileapp.py b/IPython/core/profileapp.py
index 97434e3..9a1bae5 100644
--- a/IPython/core/profileapp.py
+++ b/IPython/core/profileapp.py
@@ -181,9 +181,10 @@ def list_profile_dirs(self):
         profiles = list_profiles_in(os.getcwd())
         if profiles:
             print()
-            print("Available profiles in current directory (%s):" % os.getcwd())
-            self._print_profiles(profiles)
-        
+            print(
+                "Profiles from CWD have been removed for security reason, see CVE-2022-21699:"
+            )
+
         print()
         print("To use any of the above profiles, start IPython with:")
         print("    ipython --profile=<name>")
diff --git a/IPython/core/profiledir.py b/IPython/core/profiledir.py
index 3199dfd..2c48e4c 100644
--- a/IPython/core/profiledir.py
+++ b/IPython/core/profiledir.py
@@ -186,7 +186,7 @@ def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
         is not found, a :class:`ProfileDirError` exception will be raised.
 
         The search path algorithm is:
-        1. ``os.getcwd()``
+        1. ``os.getcwd()`` # removed for security reason.
         2. ``ipython_dir``
 
         Parameters
@@ -198,7 +198,7 @@ def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
             will be "profile_<profile>".
         """
         dirname = u'profile_' + name
-        paths = [os.getcwd(), ipython_dir]
+        paths = [ipython_dir]
         for p in paths:
             profile_dir = os.path.join(p, dirname)
             if os.path.isdir(profile_dir):
diff --git a/IPython/tests/cve.py b/IPython/tests/cve.py
new file mode 100644
index 0000000..026415a
--- /dev/null
+++ b/IPython/tests/cve.py
@@ -0,0 +1,56 @@
+"""
+Test that CVEs stay fixed. 
+"""
+
+from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
+from pathlib import Path
+import random
+import sys
+import os
+import string
+import subprocess
+import time
+
+def test_cve_2022_21699():
+    """
+    Here we test CVE-2022-21699.
+
+    We create a temporary directory, cd into it. 
+    Make a profile file that should not be executed and start IPython in a subprocess, 
+    checking for the value.
+
+
+
+    """
+
+    dangerous_profile_dir = Path('profile_default')
+
+    dangerous_startup_dir = dangerous_profile_dir / 'startup'
+    dangerous_expected = 'CVE-2022-21699-'+''.join([random.choice(string.ascii_letters) for i in range(10)])
+
+    with TemporaryWorkingDirectory() as t:
+        dangerous_startup_dir.mkdir(parents=True)
+        (dangerous_startup_dir/ 'foo.py').write_text(f'print("{dangerous_expected}")')
+        # 1 sec to make sure FS is flushed.
+        #time.sleep(1)
+        cmd = [sys.executable,'-m', 'IPython']
+        env = os.environ.copy()
+        env['IPY_TEST_SIMPLE_PROMPT'] = '1'
+
+
+        # First we fake old behavior, making sure the profile is/was actually dangerous
+        p_dangerous = subprocess.Popen(cmd + [f'--profile-dir={dangerous_profile_dir}'], env=env, stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        out_dangerous, err_dangerouns = p_dangerous.communicate(b"exit\r")
+        assert dangerous_expected in out_dangerous.decode()
+
+        # Now that we know it _would_ have been dangerous, we test it's not loaded
+        p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        out, err = p.communicate(b"exit\r")
+        assert b'IPython' in out
+        assert dangerous_expected not in out.decode()
+        assert err == b''
+
+
+