RestrictedPython 7.2a1.dev0__tar.gz → 7.3__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 (107) hide show
  1. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/CHANGES.rst +18 -4
  2. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/PKG-INFO +20 -6
  3. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/usage/basic_usage.rst +56 -0
  4. RestrictedPython-7.3/setup.py +74 -0
  5. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/Guards.py +7 -0
  6. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/Utilities.py +5 -1
  7. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/transformer.py +4 -0
  8. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/PKG-INFO +20 -6
  9. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/builtins/test_utilities.py +11 -2
  10. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_Guards.py +70 -0
  11. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_compile.py +17 -6
  12. RestrictedPython-7.2a1.dev0/setup.py +0 -79
  13. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/.readthedocs.yaml +0 -0
  14. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/CONTRIBUTING.md +0 -0
  15. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/COPYRIGHT.txt +0 -0
  16. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/LICENSE.txt +0 -0
  17. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/MANIFEST.in +0 -0
  18. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/README.rst +0 -0
  19. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/buildout.cfg +0 -0
  20. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/constraints.txt +0 -0
  21. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/Makefile +0 -0
  22. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/changes.rst +0 -0
  23. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/conf.py +0 -0
  24. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_10.ast +0 -0
  25. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_11.ast +0 -0
  26. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_12.ast +0 -0
  27. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_6.ast +0 -0
  28. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_7.ast +0 -0
  29. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_8.ast +0 -0
  30. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/ast/python3_9.ast +0 -0
  31. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from310to311.rst +0 -0
  32. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from311to312.rst +0 -0
  33. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from36to37.rst +0 -0
  34. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from37to38.rst +0 -0
  35. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from38to39.rst +0 -0
  36. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/changes_from39to310.rst +0 -0
  37. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/contributing/index.rst +0 -0
  38. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/idea.rst +0 -0
  39. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/index.rst +0 -0
  40. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/install/index.rst +0 -0
  41. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/logo.jpg +0 -0
  42. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/make.bat +0 -0
  43. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/requirements.txt +0 -0
  44. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/roadmap/index.rst +0 -0
  45. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/upgrade_dependencies/index.rst +0 -0
  46. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/usage/api.rst +0 -0
  47. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/usage/framework_usage.rst +0 -0
  48. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/usage/index.rst +0 -0
  49. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/docs/usage/policy.rst +0 -0
  50. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/setup.cfg +0 -0
  51. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/Eval.py +0 -0
  52. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/Limits.py +0 -0
  53. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/PrintCollector.py +0 -0
  54. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/__init__.py +0 -0
  55. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/_compat.py +0 -0
  56. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython/compile.py +0 -0
  57. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/SOURCES.txt +0 -0
  58. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/dependency_links.txt +0 -0
  59. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/not-zip-safe +0 -0
  60. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/requires.txt +0 -0
  61. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/src/RestrictedPython.egg-info/top_level.txt +0 -0
  62. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/__init__.py +0 -0
  63. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/builtins/test_limits.py +0 -0
  64. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/helper.py +0 -0
  65. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_NamedExpr.py +0 -0
  66. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_Utilities.py +0 -0
  67. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_compile_restricted_function.py +0 -0
  68. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_eval.py +0 -0
  69. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_imports.py +0 -0
  70. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_iterating_over_dict_items.py +0 -0
  71. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/test_print_function.py +0 -0
  72. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_arithmetic_operators.py +0 -0
  73. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_bit_wise_operators.py +0 -0
  74. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_bool_operators.py +0 -0
  75. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_comparison_operators.py +0 -0
  76. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_identity_operators.py +0 -0
  77. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_logical_operators.py +0 -0
  78. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/operators/test_unary_operators.py +0 -0
  79. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_assert.py +0 -0
  80. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_assign.py +0 -0
  81. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_async.py +0 -0
  82. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_attribute.py +0 -0
  83. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_augassign.py +0 -0
  84. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_base_types.py +0 -0
  85. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_breakpoint.py +0 -0
  86. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_call.py +0 -0
  87. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_classdef.py +0 -0
  88. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_comparators.py +0 -0
  89. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_conditional.py +0 -0
  90. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_dict_comprehension.py +0 -0
  91. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_eval_exec.py +0 -0
  92. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_fstring.py +0 -0
  93. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_functiondef.py +0 -0
  94. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_generic.py +0 -0
  95. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_global_local.py +0 -0
  96. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_import.py +0 -0
  97. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_inspect.py +0 -0
  98. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_iterator.py +0 -0
  99. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_lambda.py +0 -0
  100. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_loop.py +0 -0
  101. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_name.py +0 -0
  102. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_slice.py +0 -0
  103. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_subscript.py +0 -0
  104. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_try.py +0 -0
  105. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_with_stmt.py +0 -0
  106. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tests/transformer/test_yield.py +0 -0
  107. {RestrictedPython-7.2a1.dev0 → RestrictedPython-7.3}/tox.ini +0 -0
@@ -1,11 +1,25 @@
1
1
  Changes
2
2
  =======
3
3
 
4
- 7.2a1.dev0 (2024-03-14)
5
- -----------------------
4
+ 7.3 (2024-09-30)
5
+ ----------------
6
+
7
+ - Increase the safety level of ``safer_getattr`` allowing applications to use
8
+ it as ``getattr`` implementation. Such use should now follow the same policy
9
+ and give the same level of protection as direct attribute access in an
10
+ environment based on ``RestrictedPython``'s ``safe_builtints``.
11
+ - Prevent information leakage via ``AttributeError.obj``
12
+ and the ``string`` module.
13
+
14
+
15
+ 7.2 (2024-08-02)
16
+ ----------------
6
17
 
7
- - Allow to use the package with Python 3.13 -- Caution: No security
8
- audit has been done so far.
18
+ - Remove unneeded setuptools fossils that may cause installation problems
19
+ with recent setuptools versions.
20
+ - Add support for single mode statements / execution.
21
+ - Fix a potential breakout capability in the provided ``safer_getattr`` method
22
+ that is part of the ``safer_builtins``.
9
23
 
10
24
 
11
25
  7.1 (2024-03-14)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RestrictedPython
3
- Version: 7.2a1.dev0
3
+ Version: 7.3
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
@@ -23,7 +23,7 @@ Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: Implementation :: CPython
25
25
  Classifier: Topic :: Security
26
- Requires-Python: >=3.7, <3.14
26
+ Requires-Python: >=3.7, <3.13
27
27
  Description-Content-Type: text/x-rst
28
28
  License-File: LICENSE.txt
29
29
  Provides-Extra: test
@@ -124,11 +124,25 @@ the documentation `Contributing page
124
124
  Changes
125
125
  =======
126
126
 
127
- 7.2a1.dev0 (2024-03-14)
128
- -----------------------
127
+ 7.3 (2024-09-30)
128
+ ----------------
129
+
130
+ - Increase the safety level of ``safer_getattr`` allowing applications to use
131
+ it as ``getattr`` implementation. Such use should now follow the same policy
132
+ and give the same level of protection as direct attribute access in an
133
+ environment based on ``RestrictedPython``'s ``safe_builtints``.
134
+ - Prevent information leakage via ``AttributeError.obj``
135
+ and the ``string`` module.
136
+
137
+
138
+ 7.2 (2024-08-02)
139
+ ----------------
129
140
 
130
- - Allow to use the package with Python 3.13 -- Caution: No security
131
- audit has been done so far.
141
+ - Remove unneeded setuptools fossils that may cause installation problems
142
+ with recent setuptools versions.
143
+ - Add support for single mode statements / execution.
144
+ - Fix a potential breakout capability in the provided ``safer_getattr`` method
145
+ that is part of the ``safer_builtins``.
132
146
 
133
147
 
134
148
  7.1 (2024-03-14)
@@ -94,6 +94,62 @@ One common advanced usage would be to define an own restricted builtin dictionar
94
94
 
95
95
  There is a shortcut for ``{'__builtins__': safe_builtins}`` named ``safe_globals`` which can be imported from ``RestrictedPython``.
96
96
 
97
+ Other Usages
98
+ ------------
99
+
100
+ RestrictedPython has similar to normal Python multiple modes:
101
+
102
+ * exec
103
+ * eval
104
+ * single
105
+ * function
106
+
107
+ you can use it by:
108
+
109
+ .. testcode::
110
+
111
+ from RestrictedPython import compile_restricted
112
+
113
+ source_code = """
114
+ def do_something():
115
+ pass
116
+ """
117
+
118
+ byte_code = compile_restricted(
119
+ source_code,
120
+ filename='<inline code>',
121
+ mode='exec'
122
+ )
123
+ exec(byte_code)
124
+ do_something()
125
+
126
+ .. testcode::
127
+
128
+ from RestrictedPython import compile_restricted
129
+
130
+ byte_code = compile_restricted(
131
+ "2 + 2",
132
+ filename='<inline code>',
133
+ mode='eval'
134
+ )
135
+ eval(byte_code)
136
+
137
+
138
+ .. testcode:: single
139
+
140
+ from RestrictedPython import compile_restricted
141
+
142
+ byte_code = compile_restricted(
143
+ "2 + 2",
144
+ filename='<inline code>',
145
+ mode='single'
146
+ )
147
+ exec(byte_code)
148
+
149
+ .. testoutput:: single
150
+
151
+ 4
152
+
97
153
  Necessary setup
98
154
  ---------------
99
155
 
@@ -0,0 +1,74 @@
1
+ ##############################################################################
2
+ #
3
+ # Copyright (c) 2006 Zope Foundation and Contributors.
4
+ # All Rights Reserved.
5
+ #
6
+ # This software is subject to the provisions of the Zope Public License,
7
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
+ # FOR A PARTICULAR PURPOSE.
12
+ #
13
+ ##############################################################################
14
+ """Setup for RestrictedPython package"""
15
+
16
+ import os
17
+
18
+ from setuptools import find_packages
19
+ from setuptools import setup
20
+
21
+
22
+ def read(*rnames):
23
+ with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
24
+ return f.read()
25
+
26
+
27
+ tests_require = [
28
+ 'pytest',
29
+ 'pytest-mock',
30
+ ]
31
+
32
+ setup(name='RestrictedPython',
33
+ version='7.3',
34
+ url='https://github.com/zopefoundation/RestrictedPython',
35
+ license='ZPL 2.1',
36
+ description=(
37
+ 'RestrictedPython is a defined subset of the Python language which '
38
+ 'allows to provide a program input into a trusted environment.'),
39
+ long_description=read('README.rst') + '\n' + read('CHANGES.rst'),
40
+ long_description_content_type='text/x-rst',
41
+ classifiers=[
42
+ 'Development Status :: 6 - Mature',
43
+ 'License :: OSI Approved :: Zope Public License',
44
+ 'Programming Language :: Python',
45
+ 'Operating System :: OS Independent',
46
+ 'Programming Language :: Python :: 3',
47
+ 'Programming Language :: Python :: 3.7',
48
+ 'Programming Language :: Python :: 3.8',
49
+ 'Programming Language :: Python :: 3.9',
50
+ 'Programming Language :: Python :: 3.10',
51
+ 'Programming Language :: Python :: 3.11',
52
+ 'Programming Language :: Python :: 3.12',
53
+ 'Programming Language :: Python :: Implementation :: CPython',
54
+ 'Topic :: Security',
55
+ ],
56
+ keywords='restricted execution security untrusted code',
57
+ author='Zope Foundation and Contributors',
58
+ author_email='zope-dev@zope.org',
59
+ project_urls={
60
+ "Documentation": "https://restrictedpython.readthedocs.io/",
61
+ "Source": "https://github.com/zopefoundation/RestrictedPython",
62
+ "Tracker":
63
+ "https://github.com/zopefoundation/RestrictedPython/issues",
64
+ },
65
+ packages=find_packages('src'),
66
+ package_dir={'': 'src'},
67
+ install_requires=[],
68
+ python_requires=">=3.7, <3.13",
69
+ extras_require={
70
+ 'test': tests_require,
71
+ 'docs': ['Sphinx', 'sphinx_rtd_theme'],
72
+ },
73
+ include_package_data=True,
74
+ zip_safe=False)
@@ -18,6 +18,7 @@
18
18
  import builtins
19
19
 
20
20
  from RestrictedPython._compat import IS_PY311_OR_GREATER
21
+ from RestrictedPython.transformer import INSPECT_ATTRIBUTES
21
22
 
22
23
 
23
24
  safe_builtins = {}
@@ -246,11 +247,17 @@ def safer_getattr(object, name, default=None, getattr=getattr):
246
247
  http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
247
248
 
248
249
  """
250
+ if type(name) is not str:
251
+ raise TypeError('type(name) must be str')
249
252
  if name in ('format', 'format_map') and (
250
253
  isinstance(object, str) or
251
254
  (isinstance(object, type) and issubclass(object, str))):
252
255
  raise NotImplementedError(
253
256
  'Using the format*() methods of `str` is not safe')
257
+ if name in INSPECT_ATTRIBUTES:
258
+ raise AttributeError(
259
+ f'"{name}" is a restricted name,'
260
+ ' that is forbidden to access in RestrictedPython.')
254
261
  if name.startswith('_'):
255
262
  raise AttributeError(
256
263
  '"{name}" is an invalid attribute name because it '
@@ -29,7 +29,11 @@ class _AttributeDelegator:
29
29
  if attr in self.__excludes:
30
30
  raise NotImplementedError(
31
31
  f"{self.__mod.__name__}.{attr} is not safe")
32
- return getattr(self.__mod, attr)
32
+ try:
33
+ return getattr(self.__mod, attr)
34
+ except AttributeError as e:
35
+ e.obj = self
36
+ raise
33
37
 
34
38
 
35
39
  utility_builtins['string'] = _AttributeDelegator(string, "Formatter")
@@ -593,6 +593,10 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
593
593
  """
594
594
  return self.node_contents_visit(node)
595
595
 
596
+ def visit_Interactive(self, node):
597
+ """Allow single mode without restrictions."""
598
+ return self.node_contents_visit(node)
599
+
596
600
  def visit_List(self, node):
597
601
  """Allow list literals without restrictions."""
598
602
  return self.node_contents_visit(node)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RestrictedPython
3
- Version: 7.2a1.dev0
3
+ Version: 7.3
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
@@ -23,7 +23,7 @@ Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: Implementation :: CPython
25
25
  Classifier: Topic :: Security
26
- Requires-Python: >=3.7, <3.14
26
+ Requires-Python: >=3.7, <3.13
27
27
  Description-Content-Type: text/x-rst
28
28
  License-File: LICENSE.txt
29
29
  Provides-Extra: test
@@ -124,11 +124,25 @@ the documentation `Contributing page
124
124
  Changes
125
125
  =======
126
126
 
127
- 7.2a1.dev0 (2024-03-14)
128
- -----------------------
127
+ 7.3 (2024-09-30)
128
+ ----------------
129
+
130
+ - Increase the safety level of ``safer_getattr`` allowing applications to use
131
+ it as ``getattr`` implementation. Such use should now follow the same policy
132
+ and give the same level of protection as direct attribute access in an
133
+ environment based on ``RestrictedPython``'s ``safe_builtints``.
134
+ - Prevent information leakage via ``AttributeError.obj``
135
+ and the ``string`` module.
136
+
137
+
138
+ 7.2 (2024-08-02)
139
+ ----------------
129
140
 
130
- - Allow to use the package with Python 3.13 -- Caution: No security
131
- audit has been done so far.
141
+ - Remove unneeded setuptools fossils that may cause installation problems
142
+ with recent setuptools versions.
143
+ - Add support for single mode statements / execution.
144
+ - Fix a potential breakout capability in the provided ``safer_getattr`` method
145
+ that is part of the ``safer_builtins``.
132
146
 
133
147
 
134
148
  7.1 (2024-03-14)
@@ -7,8 +7,17 @@ def test_string_in_utility_builtins():
7
7
  from RestrictedPython.Utilities import utility_builtins
8
8
 
9
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__
10
+ # a restricted view of it (``rstring``)
11
+ rstring = utility_builtins['string']
12
+ assert rstring.__name__ == string.__name__
13
+
14
+ # ensure it does not provide access to ``string`` via
15
+ # ``AttributeError.obj``
16
+ try:
17
+ rstring.unexisting_attribute
18
+ except AttributeError as e:
19
+ assert e.obj is rstring
20
+
12
21
 
13
22
 
14
23
  def test_math_in_utility_builtins():
@@ -259,6 +259,76 @@ def test_Guards__safer_getattr__3():
259
259
  assert restricted_globals['result'] == 2
260
260
 
261
261
 
262
+ SAFER_GETATTR_BREAKOUT = """\
263
+ def g(obj, name):
264
+ # create class FakeString which inherits from str
265
+ class FakeString(str):
266
+ # overload startswith() to always return false
267
+ def startswith(self, _):
268
+ return False
269
+ return getattr(obj, FakeString(name))
270
+
271
+ # call str.__class__.__base__.__subclasses__()
272
+ subclasses = g(g(g(str, "__class__"), "__base__"), "__subclasses__")()
273
+ # traverse list of subclasses until we reach the BuiltinImporter class
274
+ x = "test"
275
+ while "BuiltinImporter" not in str(x):
276
+ x = subclasses.pop()
277
+ continue
278
+ # use BuiltinImporter to import 'os' and access to a not allowed function
279
+ result = x.load_module('os').getgid()
280
+ """
281
+
282
+
283
+ def test_Guards__safer_getattr__4():
284
+ restricted_globals = dict(
285
+ __builtins__=safe_builtins,
286
+ __name__=None,
287
+ __metaclass__=type,
288
+ # _write_=_write_,
289
+ getattr=safer_getattr,
290
+ result=None,
291
+ )
292
+
293
+ with pytest.raises(TypeError) as err:
294
+ restricted_exec(SAFER_GETATTR_BREAKOUT, restricted_globals)
295
+ assert 'type(name) must be str' == str(err.value)
296
+
297
+
298
+ SAFER_GETATTR_BREAKOUT2 = """\
299
+ g = None
300
+ leak = None
301
+ def test():
302
+ global g, leak
303
+ leak = getattr(getattr(getattr(g, "gi_frame"), "f_back"), "f_back")
304
+ yield leak
305
+ g = test()
306
+ g.send(None)
307
+ os = getattr(leak, "f_builtins").get('__import__')('os')
308
+ result = os.getgid()
309
+ """
310
+
311
+
312
+ def test_Guards__safer_getattr__5():
313
+ restricted_globals = dict(
314
+ __builtins__=safe_builtins,
315
+ __name__=None,
316
+ __metaclass__=type,
317
+ # _write_=_write_,
318
+ getattr=safer_getattr,
319
+ result=None,
320
+ )
321
+
322
+ # restricted_exec(SAFER_GETATTR_BREAKOUT2, restricted_globals)
323
+ # assert restricted_globals['result'] == 20
324
+ with pytest.raises(AttributeError) as err:
325
+ restricted_exec(SAFER_GETATTR_BREAKOUT2, restricted_globals)
326
+ assert (
327
+ '"gi_frame" is a restricted name, '
328
+ 'that is forbidden to access in RestrictedPython.'
329
+ ) == str(err.value)
330
+
331
+
262
332
  def test_call_py3_builtins():
263
333
  """It should not be allowed to access global builtins in Python3."""
264
334
  result = compile_restricted_exec('builtins["getattr"]')
@@ -160,13 +160,24 @@ def test_compile__compile_restricted_eval__used_names():
160
160
  assert result.used_names == {'a': True, 'b': True, 'x': True, 'func': True}
161
161
 
162
162
 
163
- def test_compile__compile_restricted_csingle():
163
+ def test_compile__compile_restricted_single__1():
164
164
  """It compiles code as an Interactive."""
165
- result = compile_restricted_single('4 * 6')
166
- assert result.code is None
167
- assert result.errors == (
168
- 'Line None: Interactive statements are not allowed.',
169
- )
165
+ result = compile_restricted_single('x = 4 * 6')
166
+
167
+ assert result.errors == ()
168
+ assert result.warnings == []
169
+ assert result.code is not None
170
+ locals = {}
171
+ exec(result.code, {}, locals)
172
+ assert locals["x"] == 24
173
+
174
+
175
+ def test_compile__compile_restricted__2():
176
+ """It compiles code as an Interactive."""
177
+ code = compile_restricted('x = 4 * 6', filename="<string>", mode="single")
178
+ locals = {}
179
+ exec(code, {}, locals)
180
+ assert locals["x"] == 24
170
181
 
171
182
 
172
183
  PRINT_EXAMPLE = """
@@ -1,79 +0,0 @@
1
- ##############################################################################
2
- #
3
- # Copyright (c) 2006 Zope Foundation and Contributors.
4
- # All Rights Reserved.
5
- #
6
- # This software is subject to the provisions of the Zope Public License,
7
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
- # FOR A PARTICULAR PURPOSE.
12
- #
13
- ##############################################################################
14
- """Setup for RestrictedPython package"""
15
-
16
- import os
17
-
18
- from setuptools import find_packages
19
- from setuptools import setup
20
-
21
-
22
- def read(*rnames):
23
- with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
24
- return f.read()
25
-
26
-
27
- tests_require = [
28
- 'pytest',
29
- 'pytest-mock',
30
- ]
31
-
32
-
33
- setup(
34
- name='RestrictedPython',
35
- version='7.2a1.dev0',
36
- url='https://github.com/zopefoundation/RestrictedPython',
37
- license='ZPL 2.1',
38
- description=(
39
- 'RestrictedPython is a defined subset of the Python language which '
40
- 'allows to provide a program input into a trusted environment.'
41
- ),
42
- long_description=read('README.rst') + '\n' + read('CHANGES.rst'),
43
- long_description_content_type='text/x-rst',
44
- classifiers=[
45
- 'Development Status :: 6 - Mature',
46
- 'License :: OSI Approved :: Zope Public License',
47
- 'Programming Language :: Python',
48
- 'Operating System :: OS Independent',
49
- 'Programming Language :: Python :: 3',
50
- 'Programming Language :: Python :: 3.7',
51
- 'Programming Language :: Python :: 3.8',
52
- 'Programming Language :: Python :: 3.9',
53
- 'Programming Language :: Python :: 3.10',
54
- 'Programming Language :: Python :: 3.11',
55
- 'Programming Language :: Python :: 3.12',
56
- 'Programming Language :: Python :: Implementation :: CPython',
57
- 'Topic :: Security',
58
- ],
59
- keywords='restricted execution security untrusted code',
60
- author='Zope Foundation and Contributors',
61
- author_email='zope-dev@zope.org',
62
- project_urls={
63
- "Documentation": "https://restrictedpython.readthedocs.io/",
64
- "Source": "https://github.com/zopefoundation/RestrictedPython",
65
- "Tracker": "https://github.com/zopefoundation/RestrictedPython/issues",
66
- },
67
- packages=find_packages('src'),
68
- package_dir={'': 'src'},
69
- install_requires=[
70
- ],
71
- python_requires=">=3.7, <3.14",
72
- tests_require=tests_require,
73
- extras_require={
74
- 'test': tests_require,
75
- 'docs': ['Sphinx', 'sphinx_rtd_theme'],
76
- },
77
- include_package_data=True,
78
- zip_safe=False
79
- )