-
Notifications
You must be signed in to change notification settings - Fork 24.3k
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
[REF] base: safe_eval rewrite using AST #138611
base: master
Are you sure you want to change the base?
Conversation
eedba39
to
cda00a6
Compare
c413563
to
5bd7a60
Compare
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.
@joda-odoo Hi :)
Some comments and ideas while passing :)
Cheers
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.
@joda-odoo Hi :)
A few more comments / ideas
Cheers
odoo/tools/safe_eval.py
Outdated
def __getitem__(self, item): | ||
self.__type_checker(item) | ||
return self.__type_checker(self.__obj.__getitem__(item)) | ||
|
||
def __setitem__(self, key, value): | ||
self.__type_checker(key) |
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.
SafeWrapper
is not used for standad dict, for which types is it useful so ? (__setitem__
)
Can't we just don't allow those operation ?
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.
It's mostly used for lists
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.
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.
Edit: nevermind, explore_Subscript
always encapsulate in a CheckerWrapper
(even if the type is in allowed_type)
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.
if isinstance(key, str) and "__" in key:
raise NameError(f"Forbidden name '{key}'.")
but that part is still useless, because you can call the update method
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.
I'm working on that ;)
odoo/tools/safe_eval.py
Outdated
|
||
d = new_dict | ||
|
||
def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", |
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.
If you give in the context
test = [__import__('os')]
This will crash, which is good
test[0]
but you can just do that to bypass the check
a, = test
is there anything you can do ?
same for dict if you do list(dict.values()))[0]
Either we fix that issue, or there's no point for explore_Subscript
(the less code the better, so we know excatly what is checked and what is not, and we don't think something if safe while there's a way to bypass it)
8a1652b
to
6213d34
Compare
960b060
to
256d96b
Compare
256d96b
to
95c3bd9
Compare
7ba40bb
to
a7fe9f9
Compare
f8f43ef
to
a4a700f
Compare
Context ======= `safe_eval` is Odoo's sandbox, this mechanism allows users and developpers to write templates, server actions, and more without worrying about the security risks associated with arbitrary code execution. The current version of the sandbox heavily relies on Python's bytecodes and compile-time verifications. This causes 2 major problems: 1) In every release of Python, its bytecodes are updated or modified. Which makes Odoo unusable until the security / framework team updates the whitelist of bytecode. 2) Most sandboxing issues we have faced for the last years was due to a lack of runtime checks (functions inputs (arguments) and outputs (return values)). All most every times those kind of issues were fixed with "dirty" hacks such as adding a list of "unsafe attribute" or adding a wrapper for modules that are exposing unsafe objects (such as the `sys` module) Goal of the change ================== During this rewrite we had a few goals: 1) Retain compatibility with the original version: * Find a way to keep the old checks (deny dunders, attribute storing and deleting) * Keep the same exposed API, limiting the amount of code that needs to be rewritten as much as possible 2) Add runtime checks to verify that every types passed and returns are safe by checking their type. The way that the sandbox does it is by using two set of types. One for the types we allow to instanciate (the ones that we have absolute trust, most of them are primitive types such as `str` and `int`) and the ones that we only allow as instance, this means that you CANNOT instanciate them inside of the sandbox (for example the sql cursor or the Odoo environement). 3) Eliminate the issues with the `.format` and `.format_map`. This is a well known issue within the Python security community, if you want more info : https://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
str.format are now denied in the new safe_eval
a4a700f
to
2dad991
Compare
Context
safe_eval
is Odoo's sandbox, this mechanism allows users and developpers to write templates, server actions, and more without worrying about the security risks associated with arbitrary code execution.The current version of the sandbox heavily relies on Python's bytecodes and compile-time verifications. This causes 2 major problems:
In every release of Python, its bytecodes are updated or modified.
Which makes Odoo unusable until the security / framework team updates the
whitelist of bytecode.
Most sandboxing issues we have faced for the last years was due to a
lack of runtime checks (functions inputs (arguments) and outputs
(return values)). All most every times those kind of issues were
fixed with "dirty" hacks such as adding a list of
"unsafe attribute" or adding a wrapper for modules that are exposing
unsafe objects (such as the
sys
module)Goal of the change
During this rewrite we had a few goals:
Retain compatibility with the original version:
and deleting)
to be rewritten as much as possible
Add runtime checks to verify that every types passed and returns are
safe by checking their type. The way that the sandbox does it is by
using two set of types. One for the types we allow to instanciate
(the ones that we have absolute trust, most of them are primitive
types such as
str
andint
) and the ones that we only allow asinstance, this means that you CANNOT instanciate them inside of the
sandbox (for example the sql cursor or the Odoo environement).
Eliminate the issues with the
.format
and.format_map
.This is a well known issue within the Python security community, if
you want more info : https://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
Linked with https://github.com/odoo/enterprise/pull/48919