CVE-2009-5145: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site scripting (XSS) vulnerability in ZMI pages that use the manage_tabs_message in Zope 2.11.4, 2.11.2, 2.10.9, 2.10.7, 2.10.6, 2.10.5, 2.10.4, 2.10.2, 2.10.1, 2.12.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2017-08-07T17:29Z
Repository: https://github.com/zopefoundation/Zope
Language: Python
Files changed: doc/CHANGES.rst, src/Products/PageTemplates/ZRPythonExpr.py, src/Products/PageTemplates/tests/testZRPythonExpr.py
Commit date: 2009-12-02 15:43:39 +0000
Commit message: LP #490514:  preserve tainting when calling into DTML from ZPT.

Diff: diff --git a/doc/CHANGES.rst b/doc/CHANGES.rst
index be9a5ca1c..d38e1f911 100644
--- a/doc/CHANGES.rst
+++ b/doc/CHANGES.rst
@@ -58,10 +58,12 @@ Features Added
   packages.
 
 Bugs Fixed
 ++++++++++
 
+- LP #490514:  preserve tainting when calling into DTML from ZPT.
+
 - LP #414757: Don't send a request closed event from a cloned request.
 
 - LP #418454: FTP server did not work with Python 2.6.X
 
 - Fixed issue with sending text containing ':' from MailHost.
diff --git a/src/Products/PageTemplates/ZRPythonExpr.py b/src/Products/PageTemplates/ZRPythonExpr.py
index 6e01754c4..1876cfeb3 100644
--- a/src/Products/PageTemplates/ZRPythonExpr.py
+++ b/src/Products/PageTemplates/ZRPythonExpr.py
@@ -67,10 +67,12 @@ def call_with_ns(f, ns, arg=1):
     td = Rtd()
     # prefer 'context' to 'here';  fall back to 'None'
     this = ns.get('context', ns.get('here'))
     td.this = this
     request = ns.get('request', {})
+    if hasattr(request, 'taintWrapper'):
+        request = request.taintWrapper()
     td._push(request)
     td._push(InstanceDict(td.this, td))
     td._push(ns)
     try:
         if arg==2:
diff --git a/src/Products/PageTemplates/tests/testZRPythonExpr.py b/src/Products/PageTemplates/tests/testZRPythonExpr.py
index b0d9902b5..e79c951bf 100644
--- a/src/Products/PageTemplates/tests/testZRPythonExpr.py
+++ b/src/Products/PageTemplates/tests/testZRPythonExpr.py
@@ -37,10 +37,22 @@ class MiscTests(unittest.TestCase):
             td._push(ns)
             return request
 
         result = call_with_ns(_find_request, names)
         self.assertEqual(result, {})
+
+    def test_call_with_request_preserves_tainting(self):
+        from Products.PageTemplates.ZRPythonExpr import call_with_ns
+        class Request(dict):
+            def taintWrapper(self):
+                return {'tainted': 'found'}
+        context = ['context']
+        here = ['here']
+        names = {'context' : context, 'here': here, 'request' : Request()}
+
+        found = call_with_ns(lambda td: td['tainted'], names)
+        self.assertEqual(found, 'found')
  
 def test_suite():
     return unittest.makeSuite(MiscTests)
 
 if __name__ == '__main__':

Fixed code: - LP #490514:  preserve tainting when calling into DTML from ZPT.

    if hasattr(request, 'taintWrapper'):
        request = request.taintWrapper()

    def test_call_with_request_preserves_tainting(self):
        from Products.PageTemplates.ZRPythonExpr import call_with_ns
        class Request(dict):
            def taintWrapper(self):
                return {'tainted': 'found'}
        context = ['context']
        here = ['here']
        names = {'context' : context, 'here': here, 'request' : Request()}

        found = call_with_ns(lambda td: td['tainted'], names)
        self.assertEqual(found, 'found')