Package: python-reportlab
Version: 3.1.8-3+deb8u2, 3.3.0-2+deb9u1, 3.5.13-1+deb10u1

Hi,

When I was reviewing the patch for CVE-2019-17626, the upstream fix:
https://github.com/MrBitBucket/reportlab-mirror/commit/de97afeae2adfaf129d577932caf2e455be8e606#diff-cbe131c773b3a48a9f14c3f3475dabd0L758
also
fix an unsafe exec call.

class Macro(Flowable):
    """This is not actually drawn (i.e. it has zero height)
    but is executed when it would fit in the frame.  Allows direct
    access to the canvas through the object 'canvas'"""
    def __init__(self, command):
        self.command = command
    def __repr__(self):
        return "Macro(%s)" % repr(self.command)
    def wrap(self, availWidth, availHeight):
        return (0,0)
    def draw(self):
-       exec(self.command, safer_globals(), {'canvas':self.canv})
+      rl_safe_exec(self.command, g=None, l={'canvas':self.canv})

Due to license issue and hard-to-audit code introduced, the Debian's patch
do not follow this upstream fix, which means rl_safe_exec is not involved
in Debian packages.

So, I'm able to trigger this unsafe exec by this code when using Debian
packages version 3.1.8-3+deb8u2, 3.3.0-2+deb9u1, 3.5.13-1+deb10u1:

>>> from reportlab.platypus import Macro
>>> x=Macro("open('test.txt','w').write('ok')")
>>> x.canv=None
>>> x.draw()

# ls test.txt
test.txt

----

However, with latest pip version, exception is generated:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python38\lib\site-packages\reportlab\platypus\flowables.py",
line 758, in draw
    rl_safe_exec(self.command, g=None, l={'canvas':self.canv})
  File "C:\Python38\lib\site-packages\reportlab\lib\rl_safe_eval.py",
line 1334, in __call__
    return self.env.__rl_safe_eval__(expr, g, l, self.mode, timeout=timeout,
  File "C:\Python38\lib\site-packages\reportlab\lib\rl_safe_eval.py",
line 1318, in __rl_safe_eval__
    return eval(bcode,G,L)
  File "<string>", line 1, in <module>
  File "C:\Python38\lib\site-packages\reportlab\lib\rl_safe_eval.py",
line 1041, in <lambda>
    __rl_builtins__['__rl_apply__'] = lambda func,*args,**kwds:
self.__rl_apply__(func,args,kwds)
  File "C:\Python38\lib\site-packages\reportlab\lib\rl_safe_eval.py",
line 1266, in __rl_apply__
    return func(*[a for a in self.__rl_getiter__(args)], **{k:v for
k,v in kwds.items()})
  File "C:\Python38\lib\site-packages\reportlab\lib\rl_safe_eval.py",
line 996, in __call__
    raise BadCode('missing global %s' % self.__name__)
reportlab.lib.rl_safe_eval.BadCode: missing global open

----

But I cannot find any code use this Macro class in the reportlab package,
maybe it's the caller's responsibility to ensure that the parameter
send to Macro
is sanitized.

Do you think this is a security bug?

regards,
zjuchenyuan

Reply via email to