Skip to content
This repository has been archived by the owner on May 13, 2020. It is now read-only.

Commit

Permalink
Fix security issue with (supposedly) secure templates
Browse files Browse the repository at this point in the history
  • Loading branch information
malthe committed Apr 19, 2016
1 parent 1238528 commit d896601
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 1 deletion.
4 changes: 3 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Changelog
2.2.4 (unreleased)
~~~~~~~~~~~~~~~~~~

- Nothing changed yet.
- Skip processing instruction code blocks in templates that use
the restricted evaluation engine.
[mauritsvanrees]


2.2.3 (2015-07-18)
Expand Down
23 changes: 23 additions & 0 deletions src/five/pt/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
interpreter).
"""

import re
import sys
import logging

from zope.tal.talinterpreter import TALInterpreter
from zope.interface import implements
Expand Down Expand Up @@ -44,6 +46,9 @@

InitializeClass(RepeatDict)

re_match_pi = re.compile(r'<\?python([^\w].*?)\?>', re.DOTALL)
logger = logging.getLogger('five.pt')


class Program(object):
implements(IPageTemplateProgram)
Expand Down Expand Up @@ -95,6 +100,24 @@ def __call__(self, context, macros, tal=True, **options):
@classmethod
def cook(cls, source_file, text, engine, content_type):
if engine is getEngine():
def sanitize(m):
match = m.group(1)
logger.info(
'skipped "<?python%s?>" code block in '
'Zope 2 page template object "%s".',
match, source_file
)
return ''

text, count = re_match_pi.subn(sanitize, text)
if count:
logger.warning(
"skipped %d code block%s (not allowed in "
"restricted evaluation scope)." % (
count, 's' if count > 1 else ''
)
)

expression_types = cls.secure_expression_types
else:
expression_types = cls.expression_types
Expand Down
1 change: 1 addition & 0 deletions src/five/pt/tests/pi.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p xmlns="http://www.w3.org/1999/xhtml"><?python 1/0 ?>Hello world</p>
20 changes: 20 additions & 0 deletions src/five/pt/tests/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ def test_pagetemplatefile(self):
template = template.__of__(self.folder)
self.assertTrue('world' in template())

def test_pagetemplatefile_processing_instruction_skipped(self):
from Products.PageTemplates.PageTemplateFile import PageTemplateFile

# test rendering engine
template = PageTemplateFile(os.path.join(path, "pi.pt"))
template = template.__of__(self.folder)
self.assertIn('world', template())

def test_zopepagetemplate(self):
from Products.PageTemplates.ZopePageTemplate import manage_addPageTemplate
template = manage_addPageTemplate(self.folder, 'test')
Expand All @@ -52,6 +60,18 @@ def test_zopepagetemplate(self):
import transaction
transaction.commit()

def test_zopepagetemplate_processing_instruction_skipped(self):
from Products.PageTemplates.ZopePageTemplate import manage_addPageTemplate
template = manage_addPageTemplate(self.folder, 'test')

# aq-wrap before we proceed
template = template.__of__(self.folder)

# test rendering engine
template.write(open(os.path.join(path, "pi.pt")).read())
self.assertIn('world', template())


def test_suite():
import sys
return unittest.findTestCases(sys.modules[__name__])
8 changes: 8 additions & 0 deletions src/five/pt/tests/test_viewpagetemplatefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class SimpleView(BrowserView):
index = ViewPageTemplateFile('simple.pt')


class ProcessingInstructionTestView(BrowserView):
index = ViewPageTemplateFile('pi.pt')


class LocalsView(BrowserView):
def available(self):
return 'yes'
Expand Down Expand Up @@ -95,6 +99,10 @@ def test_MissingValue(self):

self.failUnless('<span></span>' in result)

def test_processing_instruction(self):
view = ProcessingInstructionTestView(self.folder, self.folder.REQUEST)
self.assertRaises(ZeroDivisionError, view.index)


def test_suite():
import sys
Expand Down

0 comments on commit d896601

Please sign in to comment.