Skip to content

Commit 5fa1e40

Browse files
committed
Merge pull request from GHSA-pq7m-3gw7-gq5x
FIX CVE-2022-21699
1 parent 8df8971 commit 5fa1e40

File tree

6 files changed

+75
-6
lines changed

6 files changed

+75
-6
lines changed

IPython/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565
__license__ = release.license
6666
__version__ = release.version
6767
version_info = release.version_info
68+
# list of CVEs that should have been patched in this release.
69+
# this is informational and should not be relied upon.
70+
__patched_cves__ = {"CVE-2022-21699"}
71+
6872

6973
def embed_kernel(module=None, local_ns=None, **kwargs):
7074
"""Embed and start an IPython kernel in a given scope.

IPython/core/application.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def _config_file_name_changed(self, change):
133133
config_file_paths = List(Unicode())
134134
@default('config_file_paths')
135135
def _config_file_paths_default(self):
136-
return [os.getcwd()]
136+
return []
137137

138138
extra_config_file = Unicode(
139139
help="""Path to an extra config file to load.

IPython/core/profileapp.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,10 @@ def list_profile_dirs(self):
181181
profiles = list_profiles_in(os.getcwd())
182182
if profiles:
183183
print()
184-
print("Available profiles in current directory (%s):" % os.getcwd())
185-
self._print_profiles(profiles)
186-
184+
print(
185+
"Profiles from CWD have been removed for security reason, see CVE-2022-21699:"
186+
)
187+
187188
print()
188189
print("To use any of the above profiles, start IPython with:")
189190
print(" ipython --profile=<name>")

IPython/core/profiledir.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
186186
is not found, a :class:`ProfileDirError` exception will be raised.
187187
188188
The search path algorithm is:
189-
1. ``os.getcwd()``
189+
1. ``os.getcwd()`` # removed for security reason.
190190
2. ``ipython_dir``
191191
192192
Parameters
@@ -198,7 +198,7 @@ def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
198198
will be "profile_<profile>".
199199
"""
200200
dirname = u'profile_' + name
201-
paths = [os.getcwd(), ipython_dir]
201+
paths = [ipython_dir]
202202
for p in paths:
203203
profile_dir = os.path.join(p, dirname)
204204
if os.path.isdir(profile_dir):

IPython/tests/cve.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Test that CVEs stay fixed.
3+
"""
4+
5+
from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
6+
from pathlib import Path
7+
import random
8+
import sys
9+
import os
10+
import string
11+
import subprocess
12+
import time
13+
14+
def test_cve_2022_21699():
15+
"""
16+
Here we test CVE-2022-21699.
17+
18+
We create a temporary directory, cd into it.
19+
Make a profile file that should not be executed and start IPython in a subprocess,
20+
checking for the value.
21+
22+
23+
24+
"""
25+
26+
dangerous_profile_dir = Path('profile_default')
27+
28+
dangerous_startup_dir = dangerous_profile_dir / 'startup'
29+
dangerous_expected = 'CVE-2022-21699-'+''.join([random.choice(string.ascii_letters) for i in range(10)])
30+
31+
with TemporaryWorkingDirectory() as t:
32+
dangerous_startup_dir.mkdir(parents=True)
33+
(dangerous_startup_dir/ 'foo.py').write_text(f'print("{dangerous_expected}")')
34+
# 1 sec to make sure FS is flushed.
35+
#time.sleep(1)
36+
cmd = [sys.executable,'-m', 'IPython']
37+
env = os.environ.copy()
38+
env['IPY_TEST_SIMPLE_PROMPT'] = '1'
39+
40+
41+
# First we fake old behavior, making sure the profile is/was actually dangerous
42+
p_dangerous = subprocess.Popen(cmd + [f'--profile-dir={dangerous_profile_dir}'], env=env, stdin=subprocess.PIPE,
43+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
44+
out_dangerous, err_dangerouns = p_dangerous.communicate(b"exit\r")
45+
assert dangerous_expected in out_dangerous.decode()
46+
47+
# Now that we know it _would_ have been dangerous, we test it's not loaded
48+
p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE,
49+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
50+
out, err = p.communicate(b"exit\r")
51+
assert b'IPython' in out
52+
assert dangerous_expected not in out.decode()
53+
assert err == b''
54+
55+
56+

docs/source/whatsnew/version7.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
7.x Series
33
============
44

5+
=======
6+
.. _version 7.16.3:
7+
8+
IPython 7.16.3 (CVE-2022-21699)
9+
===============================
10+
11+
Fixed CVE-2022-21699, see IPython 8.0.1 release notes for informations.
12+
513
.. _version 716:
614

715
IPython 7.16.1, 7.16.2

0 commit comments

Comments
 (0)