Skip to content
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

CVE-2022-22817 Restrict builtins for ImageMath.eval() #5923

Merged
merged 1 commit into from Jan 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions Tests/test_imagemath.py
@@ -1,3 +1,5 @@
import pytest

from PIL import Image, ImageMath


Expand Down Expand Up @@ -50,6 +52,11 @@ def test_ops():
assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"


def test_prevent_exec():
with pytest.raises(ValueError):
ImageMath.eval("exec('pass')")


def test_logical():
assert pixel(ImageMath.eval("not A", images)) == 0
assert pixel(ImageMath.eval("A and B", images)) == "L 2"
Expand Down
8 changes: 8 additions & 0 deletions docs/releasenotes/9.0.0.rst
Expand Up @@ -116,6 +116,14 @@ To prevent attempts to slow down loading times for images, if an image has conse
duplicate tiles that only differ by their offset, only load the last tile. Credit to
Google's `OSS-Fuzz`_ project for finding this issue.

Restrict builtins available to ImageMath.eval
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To limit :py:class:`PIL.ImageMath` to working with images, Pillow will now restrict the
builtins available to :py:meth:`PIL.ImageMath.eval`. This will help prevent problems
arising if users evaluate arbitrary expressions, such as
``ImageMath.eval("exec(exit())")``.

Fixed ImagePath.Path array handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
7 changes: 6 additions & 1 deletion src/PIL/ImageMath.py
Expand Up @@ -246,7 +246,12 @@ def eval(expression, _dict={}, **kw):
if hasattr(v, "im"):
args[k] = _Operand(v)

out = builtins.eval(expression, args)
code = compile(expression, "<string>", "eval")
for name in code.co_names:
if name not in args and name != "abs":
raise ValueError(f"'{name}' not allowed")

out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
try:
return out.im
except AttributeError:
Expand Down