Subtle problem with introduction of new PermissionProxy

Bug #98190 reported by Garrett Smith
2
Affects Status Importance Assigned to Milestone
Zope 3
Won't Fix
Medium
Unassigned
zope.security
Won't Fix
Medium
Unassigned

Bug Description

This is subtle problem, and a little hard to explain. I've included a sample view + ZCML to illustrate -- see below.

The problem comes up when you have a view that implements IBrowserPublisher and returns itself in browserDefault (see sample below).

The code that looks up browserDefault is in zope\app\publication\browser.py starting at line 56:

56: if IBrowserPublisher.providedBy(ob):
57: # ob is already proxied, so the result of ...
58: return ob.browserDefault(request)

When PermissionProxy is used, 'ob' is a correctly security-proxied PermissionProxy instance. The permissions on 'ob' work as expected.

When 'ob' returns itself in browserDefault, however, it returns a security-proxied version of the base object -- not the permission proxy that owns the __Security_checker__. Because __Security_checker__ isn't available, the security proxy uses whatever checker is registered for the view type. In the case where zope:view is used to register a view (see sample zcml below), there will be no checker -- and the security proxy returned by browserDefault will be entirely forbidden.

This problem didn't occur before because 'proxify' either modified the utility's __Security_checker__ directly, or created a security proxy outright.

This may not actually be a 'bug', but it's *very* subtle behavior -- and hard to track down if you run into it. There are a couple work-arounds in ZCML:

 - Declare permissions for the view class
 - Use the zope:adapter directive to register the view

================== test.py =====================
from zope.interface import Interface, Attribute, implements
from zope.publisher.interfaces.browser import IBrowserPublisher

from zope.app.traversing.interfaces import TraversalError

class ISampleView(IBrowserPublisher):

    foo = Attribute("Sample attr.")

class SampleView(object):

    implements(ISampleView)

    def __init__(self, context, request):
        self.context = context
        self.request = request
        self.foo = 'Foo'

    def browserDefault(self, request):
        return self, ()

    def publishTraverse(self, request, name):
        raise TraversalError(self, name, request)

    def __call__(self):
        return self.foo

================ test-configure.zcml =================
<configure xmlns="http://namespaces.zope.org/zope" i18n_domain="test">

  <view
    name="test"
    type="zope.publisher.interfaces.browser.IBrowserRequest"
    for="*"
    provides="test.ISampleView"
    factory="test.SampleView"
    permission="zope.Public"
    allowed_interface="test.ISampleView" />

</configure>

Tags: issue security
Revision history for this message
Stephan Richter (srichter) wrote :

Changes: submitter email, importance (medium => critical)

Revision history for this message
Tres Seaver (tseaver) wrote :

Changes: topic (community => security), importance (critical => medium), new comment

Shouldn't be a release blocker: this is a corner case, with a
workaround.

Revision history for this message
Jim Fulton (jim-zope) wrote :

Changes: edited transcript, importance (medium => critical), new comment

Maybe we can take another look for this cycle. :)

Revision history for this message
Christian Theune (ctheune) wrote :

Making it medium as we have real milestone targetting now.

Changed in zope3:
importance: Critical → Medium
status: Unconfirmed → Confirmed
Tres Seaver (tseaver)
Changed in zope.security:
importance: Undecided → Medium
status: New → Confirmed
Changed in zope3:
status: Confirmed → Won't Fix
Revision history for this message
Tres Seaver (tseaver) wrote :
Changed in zope.security:
status: Confirmed → Won't Fix
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.