Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test that
str.format
checks the security for attributes that are ac…
…cessed. Part of PloneHotfix20170117. This needs zopefoundation/AccessControl#23 This was merged, but not released yet, so we add AccessControl to auto-checkout for now.
- Loading branch information
1 parent
ecfd7b1
commit 89c2040
Showing
5 changed files
with
103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ parts = | |
wsgi | ||
sources-dir = develop | ||
auto-checkout = | ||
AccessControl | ||
versions = versions | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<p tal:content="python:('%s' % context).lower()" /> | ||
<p tal:content="python:(u'%s' % context).upper()" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
from Testing.ZopeTestCase import FunctionalTestCase | ||
from zExceptions import Unauthorized | ||
|
||
import unittest | ||
|
||
|
||
BAD_STR = """ | ||
<p tal:content="python:'class of {0} is {0.__class__}'.format(context)" /> | ||
""" | ||
BAD_UNICODE = """ | ||
<p tal:content="python:u'class of {0} is {0.__class__}'.format(context)" /> | ||
""" | ||
GOOD_STR = '<p tal:content="python:(\'%s\' % context).lower()" />' | ||
GOOD_UNICODE = '<p tal:content="python:(\'%s\' % context).lower()" />' | ||
|
||
|
||
def noop(context=None): | ||
return lambda: context | ||
|
||
|
||
def hack_pt(pt, context=None): | ||
# hacks to avoid getting error in pt_render. | ||
pt.getPhysicalRoot = noop() | ||
pt._getContext = noop(context) | ||
pt._getContainer = noop(context) | ||
pt.context = context | ||
|
||
|
||
class FormatterTest(unittest.TestCase): | ||
|
||
def test_cook_zope2_page_templates_bad_str(self): | ||
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | ||
pt = ZopePageTemplate('mytemplate', BAD_STR) | ||
hack_pt(pt) | ||
self.assertRaises(Unauthorized, pt.pt_render) | ||
|
||
def test_cook_zope2_page_templates_bad_unicode(self): | ||
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | ||
pt = ZopePageTemplate('mytemplate', BAD_UNICODE) | ||
hack_pt(pt) | ||
self.assertRaises(Unauthorized, pt.pt_render) | ||
|
||
def test_cook_zope2_page_templates_good_str(self): | ||
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | ||
pt = ZopePageTemplate('mytemplate', GOOD_STR) | ||
hack_pt(pt) | ||
self.assertEqual(pt.pt_render().strip(), '<p>none</p>') | ||
|
||
def test_cook_zope2_page_templates_good_unicode(self): | ||
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | ||
pt = ZopePageTemplate('mytemplate', unicode(GOOD_UNICODE)) | ||
hack_pt(pt) | ||
self.assertEqual(pt.pt_render().strip(), '<p>none</p>') | ||
|
||
|
||
class FormatterFunctionalTest(FunctionalTestCase): | ||
|
||
def test_access_to_private_content_not_allowed_via_any_attribute(self): | ||
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | ||
# If access to _delObject would be allowed, it would still only say | ||
# something like 'bound method _delObject', without actually deleting | ||
# anything, because methods are not executed in str.format, but there | ||
# may be @properties that give an attacker secret info. | ||
pt = ZopePageTemplate('mytemplate', ''' | ||
<p tal:content="structure python:'access {0._delObject}'.format(context)" /> | ||
''') | ||
hack_pt(pt, context=self.app) | ||
self.assertRaises(Unauthorized, pt.pt_render) | ||
|
||
# Zope 3 templates are always file system templates. So we actually have | ||
# no problems allowing str.format there. | ||
|
||
def test_cook_zope3_page_templates_normal(self): | ||
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile | ||
pt = ViewPageTemplateFile('normal_zope3_page_template.pt') | ||
hack_pt(pt) | ||
# Need to pass a namespace. | ||
namespace = {'context': self.app} | ||
self.assertEqual( | ||
pt.pt_render(namespace).strip(), | ||
u'<p><application at ></p>\n' | ||
u'<p><APPLICATION AT ></p>') | ||
|
||
def test_cook_zope3_page_templates_using_format(self): | ||
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile | ||
pt = ViewPageTemplateFile('using_format_zope3_page_template.pt') | ||
hack_pt(pt) | ||
# Need to pass a namespace. | ||
namespace = {'context': self.app} | ||
self.assertEqual( | ||
pt.pt_render(namespace).strip(), | ||
u"<p>class of <application at > is " | ||
u"<class 'ofs.application.application'></p>\n" | ||
u"<p>CLASS OF <APPLICATION AT > IS " | ||
u"<CLASS 'OFS.APPLICATION.APPLICATION'></p>") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<p tal:content="python:'class of {0} is {0.__class__}'.format(context).lower()" /> | ||
<p tal:content="python:u'class of {0} is {0.__class__}'.format(context).upper()" /> |