- 
                Notifications
    You must be signed in to change notification settings 
- Fork 389
nest-server: BadRequest: 400 Bad Request: name '<function name>' is not defined #3592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| @med-ayssar Thanks for the PR! Have you confirmed that the problem still exists with NEST 3.9? It was originally reported against 3.4 and a number of things have happened in NEST Server since then, I believe. Adding @Helveg as a reviewer who has discovered security issues in the server earlier, as I am concerned about potential risks in making globals to locals. @babsey I started NEST server on my computer (Auth disabled) and confirmed that I can connect to it. But when I then try to run a script from file, I just get the content of the file displayed and  What am I doing wrong? | 
| Yeah, I tested it yesterday with the current master, and it did not work. The  To make it work, you need to set ( Export ) one environment variable, check the  | 
| 
 Example: >>> source = """
... def y():
...     return 5
... 
... def z():
...     return y()
... 
... print(z())
... """
>>> exec(source)
5
>>> exec(source, {})
5
>>> exec(source, {}, {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 8, in <module>
  File "<string>", line 6, in z
NameError: name 'y' is not definedWhich is explained by the note in the docs on  
 The solution proposed by @med-ayssar is essentially summarized as follows: globals_ = get_restricted_globals()  # Create a safe dictionary
locals_ = globals_
exec(source, globals_, locals_)which is actually equivalent to  So why are we even passing in  globals_ = ...
locals_ = {}
exec(source, globals_, locals_)
response["stdout"] = "".join(locals_["_print"].txt)The purpose of this seems to be to capture stdout while inside of the  exec("x = 5") # which is equivalent to exec(code, globals(), locals())
print(locals()["x"]) # prints 5: `exec(code)` occurs within current namespace, and would mutate/pollute it.this breaks in Python 3.13 after the change of the semantics (see python/cpython#118888). Given all this information, I think the safest and clearest way to achieve the desired behavior here is to simply not create any  def do_exec(args, kwargs):
    source_code = kwargs.get("source", "")
    source_cleaned = clean_code(source_code)
    response = dict()
    if RESTRICTION_DISABLED:
        with Capturing() as stdout:
            globals_ = globals().copy()
            globals_.update(get_modules_from_env())
            get_or_error(exec)(source_cleaned, globals_)
        if len(stdout) > 0:
            response["stdout"] = "\n".join(stdout)
    else:
        code = RestrictedPython.compile_restricted(source_cleaned, "<inline>", "exec")  # noqa
        globals_ = get_restricted_globals()
        globals_.update(get_modules_from_env())
        get_or_error(exec)(code, globals_)
        if "_print" in globals_:
            response["stdout"] = "".join(globals_["_print"].txt)The only possible change that might occur compared to the current source code (which is also a caveat of @med-ayssar's proposal) is if  | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my discourse in the conversation. The last code block is my suggested change, but I can't propose it here because it involves changing things outside of the code range I can propose suggestions to in the Review tab.
| I agree with @Helveg. As he suggested that you just remove  Let review simple samples: and with locals: To me, it looks that locals arg in exec function causes this issue #2666. | 
Fixes #2666
exec(script: string|bytes, globals: dict, locals: dict):here, we must set
localstoglobals, to be able to call the defined functions within other defined functions.