RestrictedPython 5.3a1.dev0__tar.gz → 5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/CHANGES.rst +16 -4
  2. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/MANIFEST.in +0 -1
  3. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/PKG-INFO +18 -9
  4. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/constraints.txt +3 -6
  5. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/setup.cfg +0 -11
  6. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/setup.py +4 -4
  7. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/Guards.py +5 -2
  8. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/Utilities.py +15 -1
  9. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/transformer.py +38 -4
  10. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/PKG-INFO +18 -9
  11. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/SOURCES.txt +1 -1
  12. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/builtins/test_utilities.py +4 -1
  13. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_Guards.py +130 -9
  14. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_Utilities.py +13 -0
  15. RestrictedPython-5.4/tests/transformer/test_inspect.py +60 -0
  16. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tox.ini +8 -16
  17. RestrictedPython-5.3a1.dev0/CONTRIBUTING.md +0 -23
  18. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/COPYRIGHT.txt +0 -0
  19. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/LICENSE.txt +0 -0
  20. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/README.rst +0 -0
  21. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/buildout.cfg +0 -0
  22. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/Makefile +0 -0
  23. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/changes.rst +0 -0
  24. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/conf.py +0 -0
  25. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python2_6.ast +0 -0
  26. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python2_7.ast +0 -0
  27. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_0.ast +0 -0
  28. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_1.ast +0 -0
  29. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_2.ast +0 -0
  30. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_3.ast +0 -0
  31. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_4.ast +0 -0
  32. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_5.ast +0 -0
  33. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_6.ast +0 -0
  34. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_7.ast +0 -0
  35. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_8.ast +0 -0
  36. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/ast/python3_9.ast +0 -0
  37. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from26to27.rst +0 -0
  38. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from30to31.rst +0 -0
  39. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from31to32.rst +0 -0
  40. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from32to33.rst +0 -0
  41. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from33to34.rst +0 -0
  42. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from34to35.rst +0 -0
  43. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from35to36.rst +0 -0
  44. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from36to37.rst +0 -0
  45. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from37to38.rst +0 -0
  46. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/changes_from38to39.rst +0 -0
  47. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/contributing/index.rst +0 -0
  48. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/idea.rst +0 -0
  49. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/index.rst +0 -0
  50. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/install/index.rst +0 -0
  51. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/logo.jpg +0 -0
  52. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/make.bat +0 -0
  53. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/roadmap/index.rst +0 -0
  54. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/upgrade_dependencies/index.rst +0 -0
  55. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/usage/api.rst +0 -0
  56. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/usage/basic_usage.rst +0 -0
  57. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/usage/framework_usage.rst +0 -0
  58. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/usage/index.rst +0 -0
  59. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/docs/usage/policy.rst +0 -0
  60. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/Eval.py +2 -2
  61. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/Limits.py +0 -0
  62. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/PrintCollector.py +0 -0
  63. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/__init__.py +0 -0
  64. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/_compat.py +0 -0
  65. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython/compile.py +3 -3
  66. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/dependency_links.txt +0 -0
  67. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/not-zip-safe +0 -0
  68. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/requires.txt +0 -0
  69. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/src/RestrictedPython.egg-info/top_level.txt +0 -0
  70. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/__init__.py +0 -0
  71. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/builtins/test_limits.py +0 -0
  72. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/helper.py +0 -0
  73. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_NamedExpr.py +0 -0
  74. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_compile.py +0 -0
  75. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_compile_restricted_function.py +0 -0
  76. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_eval.py +0 -0
  77. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_imports.py +0 -0
  78. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_iterating_over_dict_items.py +0 -0
  79. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_print_function.py +0 -0
  80. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/test_print_stmt.py +0 -0
  81. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_arithmetic_operators.py +0 -0
  82. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_bit_wise_operators.py +0 -0
  83. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_bool_operators.py +0 -0
  84. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_comparison_operators.py +0 -0
  85. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_identity_operators.py +0 -0
  86. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_logical_operators.py +0 -0
  87. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/operators/test_unary_operators.py +0 -0
  88. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_assert.py +0 -0
  89. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_assign.py +0 -0
  90. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_async.py +0 -0
  91. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_attribute.py +0 -0
  92. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_augassign.py +0 -0
  93. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_base_types.py +0 -0
  94. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_breakpoint.py +0 -0
  95. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_call.py +0 -0
  96. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_classdef.py +0 -0
  97. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_comparators.py +0 -0
  98. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_conditional.py +0 -0
  99. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_dict_comprehension.py +0 -0
  100. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_eval_exec.py +0 -0
  101. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_fstring.py +0 -0
  102. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_functiondef.py +0 -0
  103. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_generic.py +0 -0
  104. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_global_local.py +0 -0
  105. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_import.py +0 -0
  106. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_iterator.py +0 -0
  107. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_lambda.py +0 -0
  108. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_loop.py +0 -0
  109. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_name.py +0 -0
  110. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_slice.py +0 -0
  111. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_subscript.py +0 -0
  112. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_try.py +0 -0
  113. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_with_stmt.py +0 -0
  114. {RestrictedPython-5.3a1.dev0 → RestrictedPython-5.4}/tests/transformer/test_yield.py +0 -0
@@ -1,11 +1,23 @@
1
1
  Changes
2
2
  =======
3
3
 
4
- 5.3a1.dev0 (2022-04-13)
5
- -----------------------
4
+ 5.4 (2023-08-30)
5
+ ----------------
6
+
7
+ Fixes
8
+ +++++
9
+
10
+ - Fix information disclosure problems through
11
+ Python's "format" functionality
12
+ (``format`` and ``format_map`` methods on ``str``/``unicode`` and
13
+ their instances,
14
+ ``string.Formatter``).
15
+
16
+
17
+ 5.3 (2023-07-08)
18
+ ----------------
6
19
 
7
- - Allow to use the package with Python 3.11 -- Caution: No security audit has
8
- been done so far.
20
+ - Forbid using some attributes providing access to restricted Python internals.
9
21
 
10
22
 
11
23
  5.2 (2021-11-19)
@@ -1,6 +1,5 @@
1
1
  # Generated from:
2
2
  # https://github.com/zopefoundation/meta/tree/master/config/pure-python
3
- include *.md
4
3
  include *.rst
5
4
  include *.txt
6
5
  include buildout.cfg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RestrictedPython
3
- Version: 5.3a1.dev0
3
+ Version: 5.4
4
4
  Summary: RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment.
5
5
  Home-page: https://github.com/zopefoundation/RestrictedPython
6
6
  Author: Zope Foundation and Contributors
@@ -10,7 +10,6 @@ Project-URL: Documentation, https://restrictedpython.readthedocs.io/
10
10
  Project-URL: Source, https://github.com/zopefoundation/RestrictedPython
11
11
  Project-URL: Tracker, https://github.com/zopefoundation/RestrictedPython/issues
12
12
  Keywords: restricted execution security untrusted code
13
- Platform: UNKNOWN
14
13
  Classifier: Development Status :: 6 - Mature
15
14
  Classifier: License :: OSI Approved :: Zope Public License
16
15
  Classifier: Programming Language :: Python
@@ -26,7 +25,7 @@ Classifier: Programming Language :: Python :: 3.9
26
25
  Classifier: Programming Language :: Python :: 3.10
27
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
28
27
  Classifier: Topic :: Security
29
- Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.12
28
+ Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.11
30
29
  Description-Content-Type: text/x-rst
31
30
  Provides-Extra: test
32
31
  Provides-Extra: docs
@@ -116,11 +115,23 @@ This example directly executed in Python could harm your system.
116
115
  Changes
117
116
  =======
118
117
 
119
- 5.3a1.dev0 (2022-04-13)
120
- -----------------------
118
+ 5.4 (2023-08-30)
119
+ ----------------
120
+
121
+ Fixes
122
+ +++++
123
+
124
+ - Fix information disclosure problems through
125
+ Python's "format" functionality
126
+ (``format`` and ``format_map`` methods on ``str``/``unicode`` and
127
+ their instances,
128
+ ``string.Formatter``).
121
129
 
122
- - Allow to use the package with Python 3.11 -- Caution: No security audit has
123
- been done so far.
130
+
131
+ 5.3 (2023-07-08)
132
+ ----------------
133
+
134
+ - Forbid using some attributes providing access to restricted Python internals.
124
135
 
125
136
 
126
137
  5.2 (2021-11-19)
@@ -360,5 +371,3 @@ Bug fixes
360
371
 
361
372
  - Corresponds to the verison of the RestrictedPython package shipped
362
373
  as part of the Zope X3.0.0 release.
363
-
364
-
@@ -3,11 +3,8 @@
3
3
  # Pin Versions / Version Ranges if necessary.
4
4
  isort >= 4.3.2
5
5
  # Needed for Appveyor as long as PY2 is supported:
6
- pytest < 5 ; python_version < '3.11'
7
- # Python 3.11 needs pytest > 5
8
- pytest >= 5 ; python_version >= '3.11'
6
+ pytest < 5
7
+ pytest-html < 2
9
8
  # coverage 6+ no longer supports Python 2 and coverage results of older
10
9
  # versions cannot not combined with newer ones:
11
- coverage < 6; python_version < '3.11'
12
- # Python 3.11 requires coverage >= 6,
13
- coverage >= 6; python_version >= '3.11'
10
+ coverage < 6
@@ -18,17 +18,6 @@ ignore =
18
18
  docs/_build/html/_sources/upgrade_dependencies/*
19
19
  docs/_build/html/_sources/usage/*
20
20
 
21
- [isort]
22
- force_single_line = True
23
- combine_as_imports = True
24
- sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER
25
- known_third_party = six, docutils, pkg_resources
26
- known_zope =
27
- known_first_party =
28
- default_section = ZOPE
29
- line_length = 79
30
- lines_after_imports = 2
31
-
32
21
  [egg_info]
33
22
  tag_build =
34
23
  tag_date = 0
@@ -13,11 +13,11 @@
13
13
  ##############################################################################
14
14
  """Setup for RestrictedPython package"""
15
15
 
16
- import os
17
-
18
16
  from setuptools import find_packages
19
17
  from setuptools import setup
20
18
 
19
+ import os
20
+
21
21
 
22
22
  def read(*rnames):
23
23
  with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
@@ -32,7 +32,7 @@ tests_require = [
32
32
 
33
33
  setup(
34
34
  name='RestrictedPython',
35
- version='5.3a1.dev0',
35
+ version='5.4',
36
36
  url='https://github.com/zopefoundation/RestrictedPython',
37
37
  license='ZPL 2.1',
38
38
  description=(
@@ -70,7 +70,7 @@ setup(
70
70
  package_dir={'': 'src'},
71
71
  install_requires=[
72
72
  ],
73
- python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.12", # NOQA: E501
73
+ python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.11", # NOQA: E501
74
74
  tests_require=tests_require,
75
75
  extras_require={
76
76
  'test': tests_require,
@@ -264,9 +264,12 @@ def safer_getattr(object, name, default=None, getattr=getattr):
264
264
  http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
265
265
 
266
266
  """
267
- if isinstance(object, _compat.basestring) and name == 'format':
267
+ if name in ('format', 'format_map') and (
268
+ isinstance(object, _compat.basestring) or (
269
+ isinstance(object, type)
270
+ and issubclass(object, _compat.basestring))):
268
271
  raise NotImplementedError(
269
- 'Using format() on a %s is not safe.' % object.__class__.__name__)
272
+ 'Using the string format* methods is not safe')
270
273
  if name.startswith('_'):
271
274
  raise AttributeError(
272
275
  '"{name}" is an invalid attribute name because it '
@@ -18,7 +18,21 @@ import string
18
18
 
19
19
  utility_builtins = {}
20
20
 
21
- utility_builtins['string'] = string
21
+
22
+ class _AttributeDelegator:
23
+ def __init__(self, mod, *excludes):
24
+ """delegate attribute lookups outside *excludes* to module *mod*."""
25
+ self.__mod = mod
26
+ self.__excludes = excludes
27
+
28
+ def __getattr__(self, attr):
29
+ if attr in self.__excludes:
30
+ raise NotImplementedError(
31
+ "{}.{} is not safe".format(self.__mod.__name__, attr))
32
+ return getattr(self.__mod, attr)
33
+
34
+
35
+ utility_builtins['string'] = _AttributeDelegator(string, "Formatter")
22
36
  utility_builtins['math'] = math
23
37
  utility_builtins['random'] = random
24
38
  utility_builtins['whrandom'] = random
@@ -22,16 +22,16 @@ the parsed python code to create a modified AST for a byte code generation.
22
22
  # http://docs.plone.org/develop/styleguide/python.html
23
23
 
24
24
 
25
- import ast
26
- import contextlib
27
- import textwrap
28
-
29
25
  from ._compat import IS_PY2
30
26
  from ._compat import IS_PY3
31
27
  from ._compat import IS_PY34_OR_GREATER
32
28
  from ._compat import IS_PY35_OR_GREATER
33
29
  from ._compat import IS_PY38_OR_GREATER
34
30
 
31
+ import ast
32
+ import contextlib
33
+ import textwrap
34
+
35
35
 
36
36
  # For AugAssign the operator must be converted to a string.
37
37
  IOPERATOR_TO_STR = {
@@ -77,6 +77,32 @@ FORBIDDEN_FUNC_NAMES = frozenset([
77
77
  'breakpoint',
78
78
  ])
79
79
 
80
+ # inspect attributes. See also
81
+ # https://docs.python.org/3/library/inspect.html
82
+ INSPECT_ATTRIBUTES = frozenset([
83
+ # traceback
84
+ "tb_frame",
85
+ "tb_next",
86
+ # code
87
+ "co_code",
88
+ # frame
89
+ "f_back",
90
+ "f_builtins",
91
+ "f_code",
92
+ "f_globals",
93
+ "f_locals",
94
+ "f_trace",
95
+ # generator
96
+ "gi_frame",
97
+ "gi_code",
98
+ "gi_yieldfrom",
99
+ # coroutine
100
+ "cr_await",
101
+ "cr_frame",
102
+ "cr_code",
103
+ "cr_origin",
104
+ ])
105
+
80
106
 
81
107
  # When new ast nodes are generated they have no 'lineno' and 'col_offset'.
82
108
  # This function copies these two fields from the incoming node
@@ -923,6 +949,14 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
923
949
  '"{name}" is an invalid attribute name because it ends '
924
950
  'with "__roles__".'.format(name=node.attr))
925
951
 
952
+ if node.attr in INSPECT_ATTRIBUTES:
953
+ msg = ('"%s" is a restricted name,'
954
+ ' that is forbidden to access in RestrictedPython.')
955
+ self.error(
956
+ node,
957
+ msg % node.attr,
958
+ )
959
+
926
960
  if isinstance(node.ctx, ast.Load):
927
961
  node = self.node_contents_visit(node)
928
962
  new_node = ast.Call(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RestrictedPython
3
- Version: 5.3a1.dev0
3
+ Version: 5.4
4
4
  Summary: RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment.
5
5
  Home-page: https://github.com/zopefoundation/RestrictedPython
6
6
  Author: Zope Foundation and Contributors
@@ -10,7 +10,6 @@ Project-URL: Documentation, https://restrictedpython.readthedocs.io/
10
10
  Project-URL: Source, https://github.com/zopefoundation/RestrictedPython
11
11
  Project-URL: Tracker, https://github.com/zopefoundation/RestrictedPython/issues
12
12
  Keywords: restricted execution security untrusted code
13
- Platform: UNKNOWN
14
13
  Classifier: Development Status :: 6 - Mature
15
14
  Classifier: License :: OSI Approved :: Zope Public License
16
15
  Classifier: Programming Language :: Python
@@ -26,7 +25,7 @@ Classifier: Programming Language :: Python :: 3.9
26
25
  Classifier: Programming Language :: Python :: 3.10
27
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
28
27
  Classifier: Topic :: Security
29
- Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.12
28
+ Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.11
30
29
  Description-Content-Type: text/x-rst
31
30
  Provides-Extra: test
32
31
  Provides-Extra: docs
@@ -116,11 +115,23 @@ This example directly executed in Python could harm your system.
116
115
  Changes
117
116
  =======
118
117
 
119
- 5.3a1.dev0 (2022-04-13)
120
- -----------------------
118
+ 5.4 (2023-08-30)
119
+ ----------------
120
+
121
+ Fixes
122
+ +++++
123
+
124
+ - Fix information disclosure problems through
125
+ Python's "format" functionality
126
+ (``format`` and ``format_map`` methods on ``str``/``unicode`` and
127
+ their instances,
128
+ ``string.Formatter``).
121
129
 
122
- - Allow to use the package with Python 3.11 -- Caution: No security audit has
123
- been done so far.
130
+
131
+ 5.3 (2023-07-08)
132
+ ----------------
133
+
134
+ - Forbid using some attributes providing access to restricted Python internals.
124
135
 
125
136
 
126
137
  5.2 (2021-11-19)
@@ -360,5 +371,3 @@ Bug fixes
360
371
 
361
372
  - Corresponds to the verison of the RestrictedPython package shipped
362
373
  as part of the Zope X3.0.0 release.
363
-
364
-
@@ -1,5 +1,4 @@
1
1
  CHANGES.rst
2
- CONTRIBUTING.md
3
2
  COPYRIGHT.txt
4
3
  LICENSE.txt
5
4
  MANIFEST.in
@@ -94,6 +93,7 @@ tests/transformer/test_functiondef.py
94
93
  tests/transformer/test_generic.py
95
94
  tests/transformer/test_global_local.py
96
95
  tests/transformer/test_import.py
96
+ tests/transformer/test_inspect.py
97
97
  tests/transformer/test_iterator.py
98
98
  tests/transformer/test_lambda.py
99
99
  tests/transformer/test_loop.py
@@ -5,7 +5,10 @@ import string
5
5
 
6
6
  def test_string_in_utility_builtins():
7
7
  from RestrictedPython.Utilities import utility_builtins
8
- assert utility_builtins['string'] is string
8
+
9
+ # we no longer provide access to ``string`` itself, only to
10
+ # a restricted view of it
11
+ assert utility_builtins['string'].__name__ == string.__name__
9
12
 
10
13
 
11
14
  def test_math_in_utility_builtins():
@@ -162,7 +162,7 @@ b = a.format('world')
162
162
  """
163
163
 
164
164
 
165
- def test_Guards__safer_getattr__1():
165
+ def test_Guards__safer_getattr__1a():
166
166
  """It prevents using the format method of a string.
167
167
 
168
168
  format() is considered harmful:
@@ -173,16 +173,120 @@ def test_Guards__safer_getattr__1():
173
173
  }
174
174
  with pytest.raises(NotImplementedError) as err:
175
175
  restricted_exec(STRING_DOT_FORMAT_DENIED, glb)
176
- assert 'Using format() on a str is not safe.' == str(err.value)
176
+ assert 'Using the string format* methods is not safe' == str(err.value)
177
177
 
178
178
 
179
- UNICODE_DOT_FORMAT_DENIED = """\
179
+ # contributed by Ward Theunisse
180
+ STRING_DOT_FORMAT_MAP_DENIED = """\
181
+ a = 'Hello {foo.__dict__}'
182
+ b = a.format_map({foo:str})
183
+ """
184
+
185
+
186
+ def test_Guards__safer_getattr__1b():
187
+ """It prevents using the format method of a string.
188
+
189
+ format() is considered harmful:
190
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
191
+ """
192
+ glb = {
193
+ '__builtins__': safe_builtins,
194
+ }
195
+ with pytest.raises(NotImplementedError) as err:
196
+ restricted_exec(STRING_DOT_FORMAT_MAP_DENIED, glb)
197
+ assert 'Using the string format* methods is not safe' == str(err.value)
198
+
199
+
200
+ # contributed by Abhishek Govindarasu
201
+ STR_DOT_FORMAT_DENIED = """\
202
+ str.format('{0.__class__.__mro__[1]}', int)
203
+ """
204
+
205
+
206
+ def test_Guards__safer_getattr__1c():
207
+ """It prevents using the format method of a string.
208
+
209
+ format() is considered harmful:
210
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
211
+ """
212
+ glb = {
213
+ '__builtins__': safe_builtins,
214
+ }
215
+ with pytest.raises(NotImplementedError) as err:
216
+ restricted_exec(STR_DOT_FORMAT_DENIED, glb)
217
+ assert 'Using the string format* methods is not safe' == str(err.value)
218
+
219
+
220
+ STR_DOT_FORMAT_MAP_DENIED = """\
221
+ str.format_map('Hello {foo.__dict__}', {'foo':str})
222
+ """
223
+
224
+
225
+ def test_Guards__safer_getattr__1d():
226
+ """It prevents using the format method of a string.
227
+
228
+ format() is considered harmful:
229
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
230
+ """
231
+ glb = {
232
+ '__builtins__': safe_builtins,
233
+ }
234
+ with pytest.raises(NotImplementedError) as err:
235
+ restricted_exec(STR_DOT_FORMAT_MAP_DENIED, glb)
236
+ assert 'Using the string format* methods is not safe' == str(err.value)
237
+
238
+
239
+ USTRING_DOT_FORMAT_DENIED = """\
180
240
  a = u'Hello {}'
181
- b = a.format(u'world')
241
+ b = a.format('world')
182
242
  """
183
243
 
184
244
 
185
- def test_Guards__safer_getattr__2():
245
+ @pytest.mark.skipif(IS_PY3, reason="Python 3 lacks unicode")
246
+ def test_Guards__safer_getattr__2a():
247
+ """It prevents using the format method of a unicode.
248
+
249
+ format() is considered harmful:
250
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
251
+ """
252
+ glb = {
253
+ '__builtins__': safe_builtins,
254
+ }
255
+ with pytest.raises(NotImplementedError) as err:
256
+ restricted_exec(USTRING_DOT_FORMAT_DENIED, glb)
257
+ assert 'Using the string format* methods is not safe' == str(err.value)
258
+
259
+
260
+ # contributed by Ward Theunisse
261
+ USTRING_DOT_FORMAT_MAP_DENIED = """\
262
+ a = u'Hello {foo.__dict__}'
263
+ b = a.format_map({foo:str})
264
+ """
265
+
266
+
267
+ @pytest.mark.skipif(IS_PY3, reason="Python 3 lacks unicode")
268
+ def test_Guards__safer_getattr__2b():
269
+ """It prevents using the format method of a unicode.
270
+
271
+ format() is considered harmful:
272
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
273
+ """
274
+ glb = {
275
+ '__builtins__': safe_builtins,
276
+ }
277
+ with pytest.raises(NotImplementedError) as err:
278
+ restricted_exec(USTRING_DOT_FORMAT_MAP_DENIED, glb)
279
+ assert 'Using the string format* methods is not safe' == str(err.value)
280
+
281
+
282
+ # contributed by Abhishek Govindarasu
283
+ UNICODE_DOT_FORMAT_DENIED = """\
284
+ unicode.format(u'{0.__class__.__mro__[1]}', int)
285
+ """
286
+
287
+
288
+ @pytest.mark.skipif(IS_PY3, reason="Python 3 lacks unicode")
289
+ def test_Guards__safer_getattr__2c():
186
290
  """It prevents using the format method of a unicode.
187
291
 
188
292
  format() is considered harmful:
@@ -193,10 +297,27 @@ def test_Guards__safer_getattr__2():
193
297
  }
194
298
  with pytest.raises(NotImplementedError) as err:
195
299
  restricted_exec(UNICODE_DOT_FORMAT_DENIED, glb)
196
- if IS_PY2: # pragma: PY2
197
- assert 'Using format() on a unicode is not safe.' == str(err.value)
198
- else: # pragma: PY3
199
- assert 'Using format() on a str is not safe.' == str(err.value)
300
+ assert 'Using the string format* methods is not safe' == str(err.value)
301
+
302
+
303
+ UNICODE_DOT_FORMAT_MAP_DENIED = """\
304
+ unicode.format_map(u'Hello {foo.__dict__}', {'foo':str})
305
+ """
306
+
307
+
308
+ @pytest.mark.skipif(IS_PY3, reason="Python 3 lacks unicode")
309
+ def test_Guards__safer_getattr__2d():
310
+ """It prevents using the format method of a unicode.
311
+
312
+ format() is considered harmful:
313
+ http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
314
+ """
315
+ glb = {
316
+ '__builtins__': safe_builtins,
317
+ }
318
+ with pytest.raises(NotImplementedError) as err:
319
+ restricted_exec(UNICODE_DOT_FORMAT_MAP_DENIED, glb)
320
+ assert 'Using the string format* methods is not safe' == str(err.value)
200
321
 
201
322
 
202
323
  SAFER_GETATTR_ALLOWED = """\
@@ -1,5 +1,8 @@
1
+ import pytest
2
+
1
3
  from RestrictedPython.Utilities import reorder
2
4
  from RestrictedPython.Utilities import test
5
+ from RestrictedPython.Utilities import utility_builtins
3
6
 
4
7
 
5
8
  def test_Utilities__test_1():
@@ -30,3 +33,13 @@ def test_Utilities__reorder_1():
30
33
  _with = [('k2', 'v2'), ('k3', 'v3')]
31
34
  without = [('k2', 'v2'), ('k4', 'v4')]
32
35
  assert reorder(s, _with, without) == [('k3', 'v3')]
36
+
37
+
38
+ def test_Utilities_string_Formatter():
39
+ """Access to ``string.Formatter`` is denied."""
40
+ string = utility_builtins["string"]
41
+ # access successful in principle
42
+ assert string.ascii_lowercase == 'abcdefghijklmnopqrstuvwxyz'
43
+ with pytest.raises(NotImplementedError) as exc:
44
+ string.Formatter
45
+ assert 'string.Formatter is not safe' == str(exc.value)
@@ -0,0 +1,60 @@
1
+ from RestrictedPython import compile_restricted_exec
2
+
3
+
4
+ def test_get_inspect_frame_on_generator():
5
+ source_code = """
6
+ generator = (statement.gi_frame for _ in (1,))
7
+ generator_element = [elem for elem in generator][0]
8
+
9
+ """
10
+ result = compile_restricted_exec(source_code)
11
+ assert result.errors == (
12
+ 'Line 2: "gi_frame" is a restricted name, '
13
+ 'that is forbidden to access in RestrictedPython.',
14
+ )
15
+
16
+
17
+ def test_get_inspect_frame_back_on_generator():
18
+ source_code = """
19
+ generator = (statement.gi_frame.f_back.f_back for _ in (1,))
20
+ generator_element = [elem for elem in generator][0]
21
+
22
+ """
23
+ result = compile_restricted_exec(source_code)
24
+ assert result.errors == (
25
+ 'Line 2: "f_back" is a restricted name, '
26
+ 'that is forbidden to access in RestrictedPython.',
27
+ 'Line 2: "f_back" is a restricted name, '
28
+ 'that is forbidden to access in RestrictedPython.',
29
+ 'Line 2: "gi_frame" is a restricted name, '
30
+ 'that is forbidden to access in RestrictedPython.',
31
+ )
32
+
33
+
34
+ def test_call_inspect_frame_on_generator():
35
+ source_code = """
36
+ generator = None
37
+ frame = None
38
+
39
+ def test():
40
+ global generator, frame
41
+ frame = g.gi_frame.f_back.f_back
42
+ yield frame
43
+
44
+ generator = test()
45
+ generator.send(None)
46
+ os = frame.f_builtins.get('__import__')('os')
47
+
48
+ result = os.listdir('/')
49
+ """
50
+ result = compile_restricted_exec(source_code)
51
+ assert result.errors == (
52
+ 'Line 7: "f_back" is a restricted name, '
53
+ 'that is forbidden to access in RestrictedPython.',
54
+ 'Line 7: "f_back" is a restricted name, '
55
+ 'that is forbidden to access in RestrictedPython.',
56
+ 'Line 7: "gi_frame" is a restricted name, '
57
+ 'that is forbidden to access in RestrictedPython.',
58
+ 'Line 12: "f_builtins" is a restricted name, '
59
+ 'that is forbidden to access in RestrictedPython.',
60
+ )
@@ -11,7 +11,6 @@ envlist =
11
11
  py38
12
12
  py39
13
13
  py310
14
- py311
15
14
  docs
16
15
  coverage
17
16
  py39-datetime
@@ -23,7 +22,7 @@ deps =
23
22
  datetime: DateTime
24
23
  -cconstraints.txt
25
24
  pytest-cov
26
- !py311: coverage-python-version
25
+ coverage-python-version
27
26
  setenv =
28
27
  COVERAGE_FILE=.coverage.{envname}
29
28
  commands =
@@ -42,6 +41,8 @@ allowlist_externals =
42
41
  deps =
43
42
  coverage
44
43
  coverage-python-version
44
+ # Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it:
45
+ Sphinx < 4
45
46
  -cconstraints.txt
46
47
  setenv =
47
48
  COVERAGE_FILE=.coverage
@@ -55,25 +56,15 @@ depends = py27,py35,py36,py37,py38,py39,py39-datetime,py310,coverage
55
56
  [testenv:lint]
56
57
  basepython = python3
57
58
  skip_install = true
58
- commands =
59
- isort --check-only --diff {toxinidir}/src {toxinidir}/setup.py
60
- flake8 src setup.py
61
- check-manifest
62
- check-python-versions
63
59
  deps =
60
+ flake8
64
61
  check-manifest
65
62
  check-python-versions >= 0.19.1
66
63
  wheel
67
- flake8
68
- isort
69
-
70
- [testenv:isort-apply]
71
- basepython = python3
72
- commands_pre =
73
- deps =
74
- isort
75
64
  commands =
76
- isort {toxinidir}/src {toxinidir}/setup.py []
65
+ flake8 src setup.py
66
+ check-manifest
67
+ check-python-versions
77
68
 
78
69
  [testenv:docs]
79
70
  basepython = python3
@@ -105,6 +96,7 @@ commands =
105
96
 
106
97
  [coverage:run]
107
98
  branch = True
99
+ plugins = coverage_python_version
108
100
  source = RestrictedPython
109
101
 
110
102
  [coverage:report]
@@ -1,23 +0,0 @@
1
- <!--
2
- Generated from:
3
- https://github.com/zopefoundation/meta/tree/master/config/pure-python
4
- -->
5
- # Contributing to zopefoundation projects
6
-
7
- The projects under the zopefoundation GitHub organization are open source and
8
- welcome contributions in different forms:
9
-
10
- * bug reports
11
- * code improvements and bug fixes
12
- * documentation improvements
13
- * pull request reviews
14
-
15
- For any changes in the repository besides trivial typo fixes you are required
16
- to sign the contributor agreement. See
17
- https://www.zope.dev/developer/becoming-a-committer.html for details.
18
-
19
- Please visit our [Developer
20
- Guidelines](https://www.zope.dev/developer/guidelines.html) if you'd like to
21
- contribute code changes and our [guidelines for reporting
22
- bugs](https://www.zope.dev/developer/reporting-bugs.html) if you want to file a
23
- bug report.
@@ -12,11 +12,11 @@
12
12
  ##############################################################################
13
13
  """Restricted Python Expressions."""
14
14
 
15
- import ast
16
-
17
15
  from ._compat import IS_PY2
18
16
  from .compile import compile_restricted_eval
19
17
 
18
+ import ast
19
+
20
20
 
21
21
  if IS_PY2: # pragma: PY2
22
22
  from string import maketrans
@@ -1,11 +1,11 @@
1
- import ast
2
- import warnings
3
1
  from collections import namedtuple
4
-
5
2
  from RestrictedPython._compat import IS_CPYTHON
6
3
  from RestrictedPython._compat import IS_PY2
7
4
  from RestrictedPython.transformer import RestrictingNodeTransformer
8
5
 
6
+ import ast
7
+ import warnings
8
+
9
9
 
10
10
  CompileResult = namedtuple(
11
11
  'CompileResult', 'code, errors, warnings, used_names')