From c033e0d34d9f257e8e8242e17bfbba43e24f1256 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 31 May 2021 19:24:36 +0530 Subject: [PATCH] fix(server scripts): Restrict access to python's internal attributes --- frappe/__init__.py | 17 +++++++++++++++++ frappe/utils/safe_exec.py | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/frappe/__init__.py b/frappe/__init__.py index 9b208f7c2d..5793b224a3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1693,6 +1693,23 @@ def safe_eval(code, eval_globals=None, eval_locals=None): "round": round } + UNSAFE_ATTRIBUTES = { + # Generator Attributes + "gi_frame", "gi_code", + # Coroutine Attributes + "cr_frame", "cr_code", "cr_origin", + # Async Generator Attributes + "ag_code", "ag_frame", + # Traceback Attributes + "tb_frame", "tb_next", + # Format Attributes + "format", "format_map", + } + + for attribute in UNSAFE_ATTRIBUTES: + if attribute in code: + throw('Illegal rule {0}. Cannot use "{1}"'.format(bold(code), attribute)) + if '__' in code: throw('Illegal rule {0}. Cannot use "__"'.format(bold(code))) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index d1307a3a90..632fc5df23 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -150,6 +150,7 @@ def get_safe_globals(): # default writer allows write access out._write_ = _write out._getitem_ = _getitem + out._getattr_ = _getattr # allow iterators and list comprehension out._getiter_ = iter @@ -176,6 +177,27 @@ def _getitem(obj, key): raise SyntaxError('Key starts with _') return obj[key] +def _getattr(object, name, default=None): + # guard function for RestrictedPython + # allow any key to be accessed as long as + # 1. it does not start with an underscore (safer_getattr) + # 2. it is not an UNSAFE_ATTRIBUTES + + UNSAFE_ATTRIBUTES = { + # Generator Attributes + "gi_frame", "gi_code", + # Coroutine Attributes + "cr_frame", "cr_code", "cr_origin", + # Async Generator Attributes + "ag_code", "ag_frame", + # Traceback Attributes + "tb_frame", "tb_next", + } + + if isinstance(name, str) and (name in UNSAFE_ATTRIBUTES): + raise SyntaxError("{name} is an unsafe attribute".format(name=name)) + return RestrictedPython.Guards.safer_getattr(object, name, default=default) + def _write(obj): # guard function for RestrictedPython # allow writing to any object