Skip to content

Commit ad73a9c

Browse files
committed
Issue python#16400: Add command line option for isolated mode.
-I Run Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code.
1 parent 562d9cb commit ad73a9c

File tree

11 files changed

+77
-10
lines changed

11 files changed

+77
-10
lines changed

Doc/c-api/init.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,11 @@ Process-wide parameters
329329
330330
.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv)
331331
332-
This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set to 1.
332+
This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set
333+
to 1 unless the :program:`python` interpreter was started with the
334+
:option:`-I`.
335+
336+
.. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`.
333337
334338
335339
.. c:function:: void Py_SetPythonHome(wchar_t *home)

Doc/using/cmdline.rst

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Command line
2424

2525
When invoking Python, you may specify any of these options::
2626

27-
python [-bBdEhiOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
27+
python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
2828

2929
The most common use case is, of course, a simple invocation of a script::
3030

@@ -175,6 +175,8 @@ Generic options
175175
Python 3.0
176176

177177

178+
.. _using-on-misc-options:
179+
178180
Miscellaneous options
179181
~~~~~~~~~~~~~~~~~~~~~
180182

@@ -213,6 +215,17 @@ Miscellaneous options
213215
raises an exception. See also :envvar:`PYTHONINSPECT`.
214216

215217

218+
.. cmdoption:: -I
219+
220+
Run Python in isolated mode. This also implies -E and -s.
221+
In isolated mode :data:`sys.path` contains neither the script's directory nor
222+
the user's site-packages directory. All :envvar:`PYTHON*` environment
223+
variables are ignored, too. Further restrictions may be imposed to prevent
224+
the user from injecting malicious code.
225+
226+
.. versionadded:: 3.4
227+
228+
216229
.. cmdoption:: -O
217230

218231
Turn on basic optimizations. This changes the filename extension for
@@ -398,7 +411,7 @@ Environment variables
398411
---------------------
399412

400413
These environment variables influence Python's behavior, they are processed
401-
before the command-line switches other than -E. It is customary that
414+
before the command-line switches other than -E or -I. It is customary that
402415
command-line switches override environmental variables where there is a
403416
conflict.
404417

Doc/whatsnew/3.4.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ Significantly Improved Library Modules:
107107

108108
Security improvements:
109109

110-
* None yet.
110+
* command line option for :ref:`isolated mode <using-on-misc-options>`,
111+
:issue:`16499`.
111112

112113
Please read on for a comprehensive list of user-facing changes.
113114

Include/pydebug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
2020
PyAPI_DATA(int) Py_NoUserSiteDirectory;
2121
PyAPI_DATA(int) Py_UnbufferedStdioFlag;
2222
PyAPI_DATA(int) Py_HashRandomizationFlag;
23+
PyAPI_DATA(int) Py_IsolatedFlag;
2324

2425
/* this is a wrapper around getenv() that pays attention to
2526
Py_IgnoreEnvironmentFlag. It should be used for getting variables like

Lib/test/test_cmd_line.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import test.support, unittest
66
import os
7+
import shutil
78
import sys
89
import subprocess
910
import tempfile
@@ -439,6 +440,31 @@ def test_unknown_options(self):
439440
self.assertEqual(b'', out)
440441

441442

443+
def test_isolatedmode(self):
444+
self.verify_valid_flag('-I')
445+
self.verify_valid_flag('-IEs')
446+
rc, out, err = assert_python_ok('-I', '-c',
447+
'from sys import flags as f; '
448+
'print(f.no_user_site, f.ignore_environment, f.isolated)',
449+
# dummyvar to prevent extranous -E
450+
dummyvar="")
451+
self.assertEqual(out.strip(), b'1 1 1')
452+
with test.support.temp_cwd() as tmpdir:
453+
fake = os.path.join(tmpdir, "uuid.py")
454+
main = os.path.join(tmpdir, "main.py")
455+
with open(fake, "w") as f:
456+
f.write("raise RuntimeError('isolated mode test')\n")
457+
with open(main, "w") as f:
458+
f.write("import uuid\n")
459+
f.write("print('ok')\n")
460+
self.assertRaises(subprocess.CalledProcessError,
461+
subprocess.check_output,
462+
[sys.executable, main], cwd=tmpdir,
463+
stderr=subprocess.DEVNULL)
464+
out = subprocess.check_output([sys.executable, "-I", main],
465+
cwd=tmpdir)
466+
self.assertEqual(out.strip(), b"ok")
467+
442468
def test_main():
443469
test.support.run_unittest(CmdLineTest)
444470
test.support.reap_children()

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ def test_sys_flags(self):
515515
attrs = ("debug",
516516
"inspect", "interactive", "optimize", "dont_write_bytecode",
517517
"no_user_site", "no_site", "ignore_environment", "verbose",
518-
"bytes_warning", "quiet", "hash_randomization")
518+
"bytes_warning", "quiet", "hash_randomization", "isolated")
519519
for attr in attrs:
520520
self.assertTrue(hasattr(sys.flags, attr), attr)
521521
self.assertEqual(type(getattr(sys.flags, attr)), int, attr)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Projected Release date: 2013-09-08
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #16400: Add command line option for isolated mode.
14+
1315
- Issue #15301: Parsing fd, uid, and gid parameters for builtins
1416
in Modules/posixmodule.c is now far more robust.
1517

Misc/python.man

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@ python \- an interpreted, interactive, object-oriented programming language
2626
.B \-i
2727
]
2828
[
29-
.B \-m
30-
.I module-name
29+
.B \-I
3130
]
3231
.br
3332
[
33+
.B \-m
34+
.I module-name
35+
]
36+
[
3437
.B \-q
3538
]
3639
[
@@ -139,6 +142,13 @@ command. It does not read the $PYTHONSTARTUP file. This can be
139142
useful to inspect global variables or a stack trace when a script
140143
raises an exception.
141144
.TP
145+
.B \-I
146+
Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-S\fP. In
147+
isolated mode sys.path contains neither the script’s directory nor the user’s
148+
site-packages directory. All PYTHON* environment variables are ignored, too.
149+
Further restrictions may be imposed to prevent the user from injecting
150+
malicious code.
151+
.TP
142152
.BI "\-m " module-name
143153
Searches
144154
.I sys.path

Modules/main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static wchar_t **orig_argv;
4343
static int orig_argc;
4444

4545
/* command line options */
46-
#define BASE_OPTS L"bBc:dEhiJm:OqRsStuvVW:xX:?"
46+
#define BASE_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?"
4747

4848
#define PROGRAM_OPTS BASE_OPTS
4949

@@ -65,6 +65,7 @@ Options and arguments (and corresponding environment variables):\n\
6565
static char *usage_2 = "\
6666
-i : inspect interactively after running script; forces a prompt even\n\
6767
if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
68+
-I : isolate Python from the user's environment (implies -E and -s)\n\
6869
-m mod : run library module as a script (terminates option list)\n\
6970
-O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
7071
-OO : remove doc-strings in addition to the -O optimizations\n\
@@ -426,6 +427,12 @@ Py_Main(int argc, wchar_t **argv)
426427
Py_InteractiveFlag++;
427428
break;
428429

430+
case 'I':
431+
Py_IsolatedFlag++;
432+
Py_NoUserSiteDirectory++;
433+
Py_IgnoreEnvironmentFlag++;
434+
break;
435+
429436
/* case 'J': reserved for Jython */
430437

431438
case 'O':

Python/pythonrun.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
112112
int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
113113
int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
114114
int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
115+
int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
115116

116117
PyThreadState *_Py_Finalizing = NULL;
117118

0 commit comments

Comments
 (0)