Skip to content

Commit

Permalink
- Fixed issue 574: security exposure of TALES namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Theune committed Aug 15, 2006
1 parent 48c5509 commit 4d637e1
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 27 deletions.
63 changes: 63 additions & 0 deletions configure.zcml
@@ -0,0 +1,63 @@
<configure xmlns="http://namespaces.zope.org/zope">

<class class=".viewpagetemplatefile.BoundPageTemplate">
<allow attributes="__call__ __str__ __name__" />
</class>

<adapter
for="*"
provides="zope.traversing.interfaces.IPathAdapter"
factory=".talesapi.ZopeTalesAPI"
name="zope"
/>

<class class=".talesapi.ZopeTalesAPI">
<allow interface="zope.tales.interfaces.ITALESFunctionNamespace"/>
<allow attributes="title description created modified name title_or_name size"/>
</class>

<adapter
for="*"
provides="zope.traversing.interfaces.IPathAdapter"
factory=".urlquote.URLQuote"
name="url"/>

<class class=".urlquote.URLQuote">
<allow attributes="quote quote_plus unquote unquote_plus"/>
</class>

<class class="zope.tales.tales.Iterator">
<allow interface="zope.tales.interfaces.ITALESIterator" />
</class>

<class class=".engine.ZopePathExpr">
<allow attributes="__call__" />
</class>
<class class=".engine.TrustedZopePathExpr">
<allow attributes="__call__" />
</class>
<class class=".engine.ZopePythonExpr">
<allow attributes="__call__" />
</class>
<class class=".engine.PythonExpr">
<allow attributes="__call__" />
</class>

<class class="zope.tales.expressions.StringExpr">
<allow attributes="__call__" />
</class>
<class class="zope.tales.expressions.NotExpr">
<allow attributes="__call__" />
</class>
<class class="zope.tales.expressions.DeferExpr">
<allow attributes="__call__" />
</class>

<adapter
for="zope.app.pagetemplate.viewpagetemplatefile.BoundPageTemplate
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.publisher.interfaces.browser.IBrowserPublisher"
factory="zope.app.publication.traversers.NoTraverser"
/>

</configure>
60 changes: 33 additions & 27 deletions engine.py
Expand Up @@ -249,7 +249,34 @@ def namespace(object):
return namespace


class ZopeEngine(ExpressionEngine):
class ZopeBaseEngine(ExpressionEngine):

_create_context = ZopeContext

def __init__(self):
ExpressionEngine.__init__(self)
self.namespaces = AdapterNamespaces()

def getContext(self, __namespace=None, **namespace):
if __namespace:
if namespace:
namespace.update(__namespace)
else:
namespace = __namespace

context = self._create_context(self, namespace)

# Put request into context so path traversal can find it
if 'request' in namespace:
context.request = namespace['request']

# Put context into context so path traversal can find it
if 'context' in namespace:
context.context = namespace['context']

return context

class ZopeEngine(ZopeBaseEngine):
"""Untrusted expression engine.
This engine does not allow modules to be imported; only modules
Expand Down Expand Up @@ -355,33 +382,12 @@ class ZopeEngine(ExpressionEngine):
"""

_create_context = ZopeContext

def __init__(self):
ExpressionEngine.__init__(self)
self.namespaces = AdapterNamespaces()

def getContext(self, __namespace=None, **namespace):
if __namespace:
if namespace:
namespace.update(__namespace)
else:
namespace = __namespace

context = self._create_context(self, namespace)

# Put request into context so path traversal can find it
if 'request' in namespace:
context.request = namespace['request']

# Put context into context so path traversal can find it
if 'context' in namespace:
context.context = namespace['context']

return context

def getFunctionNamespace(self, namespacename):
""" Returns the function namespace """
return ProxyFactory(
super(ZopeEngine, self).getFunctionNamespace(namespacename))

class TrustedZopeEngine(ZopeEngine):
class TrustedZopeEngine(ZopeBaseEngine):
"""Trusted expression engine.
This engine allows modules to be imported::
Expand Down
55 changes: 55 additions & 0 deletions tests/test_engine.py
@@ -0,0 +1,55 @@
##############################################################################
#
# Copyright (c) 2004-2006 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Doc tests for the pagetemplate's 'engine' module
$Id$
"""
import unittest
from zope.testing.doctestunit import DocTestSuite

import zope.component
from zope.app.pagetemplate.engine import _Engine
from zope.proxy import isProxy
from zope.traversing.interfaces import IPathAdapter

class DummyNamespace(object):

def __init__(self, context):
self.context = context

class EngineTests(unittest.TestCase):

def setUp(self):
gsm = zope.component.getGlobalSiteManager()
gsm.registerAdapter(DummyNamespace, required=(), provided=IPathAdapter, name='test')

def tearDown(self):
gsm = zope.component.getGlobalSiteManager()
gsm.unregisterAdapter(DummyNamespace, required=(), provided=IPathAdapter, name='test')

def test_issue574(self):
engine = _Engine()
namespace = engine.getFunctionNamespace('test')
self.failUnless(isProxy(namespace))


def test_suite():
suite = unittest.TestSuite()
suite.addTest(DocTestSuite('zope.app.pagetemplate.engine'))
suite.addTest(unittest.makeSuite(EngineTests))
return suite

if __name__ == '__main__':
unittest.main(defaultTest='test_suite')

0 comments on commit 4d637e1

Please sign in to comment.