2626 DefaultUnicodeEncodingConflictResolver
2727from Products .PageTemplates .unicodeconflictresolver import \
2828 PreferredCharsetResolver
29+ from Products .PageTemplates .ZopePageTemplate import ZopePageTemplate
2930from zExceptions import NotFound
3031from zope .component import provideUtility
32+ from zope .location .interfaces import LocationError
3133from zope .traversing .adapters import DefaultTraversable
3234
3335from .util import useChameleonEngine
@@ -37,6 +39,10 @@ class AqPageTemplate(Implicit, PageTemplate):
3739 pass
3840
3941
42+ class AqZopePageTemplate (Implicit , ZopePageTemplate ):
43+ pass
44+
45+
4046class Folder (util .Base ):
4147 pass
4248
@@ -74,6 +80,7 @@ def setUp(self):
7480 self .folder = f = Folder ()
7581 f .laf = AqPageTemplate ()
7682 f .t = AqPageTemplate ()
83+ f .z = AqZopePageTemplate ('testing' )
7784 self .policy = UnitTestSecurityPolicy ()
7885 self .oldPolicy = SecurityManager .setSecurityPolicy (self .policy )
7986 noSecurityManager () # Use the new policy.
@@ -226,9 +233,45 @@ def test_underscore_traversal(self):
226233 t ()
227234
228235 t .write ('<p tal:define="p nocall: random/_itertools/repeat"/>' )
229- with self .assertRaises (NotFound ):
236+ with self .assertRaises (( NotFound , LocationError ) ):
230237 t ()
231238
232239 t .write ('<p tal:content="random/_itertools/repeat/foobar"/>' )
240+ with self .assertRaises ((NotFound , LocationError )):
241+ t ()
242+
243+ def test_module_traversal (self ):
244+ t = self .folder .z
245+
246+ # Need to reset to the standard security policy so AccessControl
247+ # checks are actually performed. The test setup initializes
248+ # a policy that circumvents those checks.
249+ SecurityManager .setSecurityPolicy (self .oldPolicy )
250+ noSecurityManager ()
251+
252+ # The getSecurityManager function is explicitly allowed
253+ content = ('<p tal:define="a nocall:%s"'
254+ ' tal:content="python: a().getUser().getUserName()"/>' )
255+ t .write (content % 'modules/AccessControl/getSecurityManager' )
256+ self .assertEqual (t (), '<p>Anonymous User</p>' )
257+
258+ # Anything else should be unreachable and raise NotFound:
259+ # Direct access through AccessControl
260+ t .write ('<p tal:define="a nocall:modules/AccessControl/users"/>' )
261+ with self .assertRaises (NotFound ):
262+ t ()
263+
264+ # Indirect access through an intermediary variable
265+ content = ('<p tal:define="mod nocall:modules/AccessControl;'
266+ ' must_fail nocall:mod/users"/>' )
267+ t .write (content )
268+ with self .assertRaises (NotFound ):
269+ t ()
270+
271+ # Indirect access through an intermediary variable and a dictionary
272+ content = ('<p tal:define="mod nocall:modules/AccessControl;'
273+ ' a_dict python: {\' unsafe\' : mod};'
274+ ' must_fail nocall: a_dict/unsafe/users"/>' )
275+ t .write (content )
233276 with self .assertRaises (NotFound ):
234277 t ()
0 commit comments