RFC: backward compatibility of PythonScript bindings for 2.6.4 / 2.7.0
Hi all - We recently made Zope 2.6.4-rc1 and 2.7.0-rc1 releases which fix a number of issues that were introduced in the Q4 security audit work and the resulting 2.6.3 and 2.7.0-b4 releases. The initial feedback is very good, and at this point I am aware of only one outstanding issue - but it is a sticky one and I want to get some community feedback before deciding exactly how to address it. Background: one of the holes fixed in the security audit was that the current user's access to 'context' and 'container' in a Python Script was not checked when those names were bound to the script for execution. This meant that theoretically a script could have a handle to an object (like the script container) that the user really didn't have permission for. Subsequent attribute accesses or attempted method calls would likely still fail since a security check *would* be performed on those actions, but in principle the script shouldn't have been allowed to get that initial handle to the object. The fix for this was straightforward - do a security check on 'context' and 'container' before binding those objects when the script is getting ready to execute. While this is definitely the Right Thing To Do (tm) from a security standpoint, it poses a bit of a backwards compatibility problem because: - By default, all Python Scripts bind both 'context' and 'container'. This means that all existing Python Scripts in applications, portal tools, etc. have those bindings unless they have been manually changed. - A standard CMF / Plone idiom is to put scripts inside of portal tools (workflow is a primary example). Very often the users who execute the scripts (as a part of workflow, for example) **do not have access to the tool containing the scripts**. These two facts did not cause a problem before, because the security check for the 'container' binding was not being performed at bind-time. Now that it is, many scripts will not work because the user will not have access to the tool containing the script. Worse, the binding check will cause an unauthorized error **even if the script doesn't actually use the 'container' variable, because all existing Python Scripts already have that binding defined by default ;( So as things stand, the way the binding check currently works will cause problems for most everyone using a workflow tool or other tools containing scripts where the user doesn't have access to the script container (the tool itself). This is likely to be a fairly large number of people / sites. I'd like to propose a solution that will hopefully affect far fewer people, while still doing the right thing with regard to security. Currently, if the executing user does not have access to either 'context' or 'container', an Unauthorized exception will be raised at bind-time. *This will happen even if the script does not use either of those names*, which is the root of the problem. I propose to change that behavior so that if the security check on either 'context' or 'container' fails, that name will be bound to None rather than raise an Unauthorized. The effect of that change on existing sites would be: - Existing scripts living in tools which *don't* reference 'container' in their code will continue to work as before without any changes on the part of the site admin - Existing scripts that *do* refer to 'container' in their code (and if the user doesn't have access to it) will break, since 'container' will now be 'None' rather than what the script thought it would be. The fix for such sites is to make sure the user has the appropriate access on the script container. What I like about this is that it potentially requires direct action from fewer site admins. IOW, you only have to fix your permissions if you were already doing something that the security system should have been preventing before. What I don't like is that it is somewhat magical, and now the error you would get (probably 'None has no attribute xxx') if the user doesn't have access to the container doesn't tell you the real problem. That is likely to be compounded by the fact that some site admins will be saved from having to care immediately by this magic, then run into it later, when they might be thoroughly confused if they didn't happen to read this thread as it went by ;) The alternative is to take the 'hard-line' and say that site admins need to visit their script containers and ensure that either a) the users of the scripts have the appropriate permissions on the container or b) they remove the 'container' binding from their scripts if it is not appropriate to give the users access to the script container. Sorry this was so long, but I think these kinds of backward compatibility vs. consistency conundrums require some community buy-in on the path chosen, since *someone* will be unhappy and have to do some manual fixing no matter what. Thoughts? Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
On Wed, 2004-01-21 at 10:42, Brian Lloyd wrote:
What I don't like is that it is somewhat magical, and now the error you would get (probably 'None has no attribute xxx') if the user doesn't have access to the container doesn't tell you the real problem.
What if you used a special object that would produce a useful error message if the user tries to access the container. Assuming an access involves an attribute access: class UnauthorizedContext: def __getattr__(self, attr): raise Unauthorized("user does not have access to context") I'm sure the details aren't right, but I think the idea is clear enough. Jeremy
Jeremy Hylton wrote at 2004-1-21 11:44 -0500:
On Wed, 2004-01-21 at 10:42, Brian Lloyd wrote:
What I don't like is that it is somewhat magical, and now the error you would get (probably 'None has no attribute xxx') if the user doesn't have access to the container doesn't tell you the real problem.
What if you used a special object that would produce a useful error message if the user tries to access the container. Assuming an access involves an attribute access:
class UnauthorizedContext:
def __getattr__(self, attr): raise Unauthorized("user does not have access to context")
I'm sure the details aren't right, but I think the idea is clear enough.
+1 -- Dieter
I think the biggest problem is to notify everyone of this change. I like the option of binding non authorized container to None, if the admins are notified about this behavior, they will know where that error (if there will be some error) came from. Best Regards, -- Mauricio Souza Lima Web Developer VARIG Brazil - GGTI mauricio.lima@varig.com
-----Original Message----- From: zope-bounces@zope.org [mailto:zope-bounces@zope.org]On Behalf Of Brian Lloyd Sent: Wednesday, January 21, 2004 12:42 PM To: zope@zope.org; zope-dev@zope.org Subject: [Zope] RFC: backward compatibility of PythonScript bindings for2.6.4 / 2.7.0
Hi all -
We recently made Zope 2.6.4-rc1 and 2.7.0-rc1 releases which fix a number of issues that were introduced in the Q4 security audit work and the resulting 2.6.3 and 2.7.0-b4 releases.
The initial feedback is very good, and at this point I am aware of ...
On Wed, Jan 21, 2004 at 10:42:11AM -0500, Brian Lloyd wrote:
These two facts did not cause a problem before, because the security check for the 'container' binding was not being performed at bind-time.
One question - what *is* bind time? Is the container bound when the script is called? -- Paul Winkler http://www.slinkp.com Look! Up in the sky! It's THE PIDDLE! (random hero from isometric.spaceninja.com)
These two facts did not cause a problem before, because the security check for the 'container' binding was not being performed at bind-time.
One question - what *is* bind time? Is the container bound when the script is called?
Yes - all of the bindings are figured out at the time the script is called. Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
participants (5)
-
Brian Lloyd -
Dieter Maurer -
Jeremy Hylton -
Mauricio Souza Lima -
Paul Winkler