Closed dopc closed 8 months ago
dopc wrote at 2024-1-3 23:40 -0800:
...
What I did:
I just tried the below code. However, it failed. It is because of that line.
from RestrictedPython import compile_restricted, safe_builtins safe_builtins['__import__'] = __import__ source_code = "__import__('numpy').array([3,5])" byte_code = compile_restricted( source_code, mode='eval', ) result = eval(byte_code, {'__builtins__': safe_builtins}, None)
SyntaxError: ('Line 1: "__import__" is an invalid variable name because it starts with "_"',)
Names starting with _
are (by convention) special in Python.
RestrictedPython
uses as (very deeply) built-in policy, never to allow access
to a variable starting with _
.
As a consequence, code to be run by RestrictedPython
cannot access
variable starting with _
and especially __import__
.
You can work around by providing an import functionality via
a name not starting with _
, e.g. restricted_import
.
Hi @dopc
first of all, yes, RestrictedPython might be a good solution or inspiration to secure a single-line Python expression execution. My first thought by reading your code example was, why do you would like to allow an __import__(<name>)
expression? It neither looks Pythonic nor readable but allow a certain import or access statement. But yes an statement would break your one-line- requirement.
I would suggest, to go with an extended set of safe_builtins or utility_builtins (see https://github.com/zopefoundation/RestrictedPython/blob/master/src/RestrictedPython/Utilities.py) and explicitly allow certain functions.
Your example could look like this:
from RestrictedPython import compile_restricted, safe_builtins
from numpy import array
safe_builtins['array'] = array
source_code = "array([3,5])"
byte_code = compile_restricted(
source_code,
mode='eval',
)
result = eval(byte_code, {'__builtins__': safe_builtins}, None)
@d-maurer
def guarded_import(name, *args, **kwargs):
if name =='os': # now allow to import os
raise RuntimeError('cannot import os')
return __import__(name, *args, **kwargs)
from RestrictedPython import compile_restricted, safe_builtins
safe_builtins['guarded_import'] = guarded_import
source_code = "guarded_import('numpy').array([3, 5])"
byte_code = compile_restricted(
source_code,
mode='eval',
)
result = eval(byte_code, {'__builtins__': safe_builtins}, None)
It worked as above by using a function from #225 , thanks.
@loechel Your points about my code make sense to me. I will consider your suggestions to make my solution better. Thanks!
BUG/PROBLEM REPORT / FEATURE REQUEST
Hey, thanks for this great project. I have an application which allows users to run a single Python expression. I want to restrict some imports and functions. Therefore I want to utilize RestrictedPython for that.
In my application users may use
__import__
function directly. I am planning to write a custom import function. I have read aboutguarded_import
. However, I want to try the simplest one first in the below experiment. So in this issue, I am reporting about that.What I did:
I just tried the below code. However, it failed. It is because of that line.
SyntaxError: ('Line 1: "__import__" is an invalid variable name because it starts with "_"',)
What I expect to happen:
Then I give
None
as the policy and it run.array([3, 5])
What I want to ask:
So, I want to ask about the
policy
and using__import__
directly like my above example.policy
for my case?None
as thepolicy
a "bad" thing for my case?What version of Python and Zope/Addons I am using: