[Dev] Coding guidelines: checking parameters

Heikki Toivonen heikki at osafoundation.org
Thu Aug 5 11:51:10 PDT 2004

One security mantra is to "check all inputs". Obviously this means to 
check all input you read from files, users, network and so forth. But it 
also means that your functions should check all parameters.

This last piece seems to go against Python principles. In Python, the 
idiom is to just use the things and rely on Python throwing exceptions. 
And in fact, checkin parameters is made even harder in Python because 
you can't even rely on the type of the parameters. All in all, lots of 
problems from security perspective.

We discussed in the IRC hours that I should give an example how this 
could be problematic. These are a bit contrived, but should make the point.

# no parameter checks
class Session:
     def sessionadder(s):
        if not hasattr(self, 'sessions'):
            self.sessions = s
        sessions += s

Here, the first caller always succeeds. The second one succeeds if the 
type of s is the same on the second call and it supports addition. The 
assumption is you only add positive integers to sessions, but it is not 
enforced. Further let's assume that the first ten sessions are granted 
extra privileges, and you can see how this could become catastrophic.

Another example with exceptions:

# exceptions not taken into account
class MyURL:
     def check(self, url, port=80):
         self.isSafe = True
         if url.lower()[6] != 'https:':
             self.isSafe = False

     myurl = MyURL().check(123456789034567)

if myurl.isSafe:
     # Ok, we checked that it is https site, send the credit card number

Here the caller assumed check() would be able to cope with numeric 
internet addresses, and that it would be automatically able to fill in 
the protocol.

Obviously bad code, but that's where security problems come from. Real 
world cases may not be this simple, and can be hard to figure out. And I 
think these kinds of problems can happen more easily when the language 
itself encourages you to not check inputs.

The fix here should not be to rely on fixing the callers, because you 
can never fix all the callers, especially since there can be new callers 
you have no control over.

The fix is to fix the sessionadder() and check() functions.  Your 
functions should fail in safe ways. It's easy to say: "Don't set 
permanent state until you are sure nothing can go wrong." But how do you 
do that when almost everything can throw an exception?

What is the Pythonic way to be robust in the face of bad (even 
malicious) callers and fail safe?

   Heikki Toivonen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 249 bytes
Desc: OpenPGP digital signature
Url : http://lists.osafoundation.org/pipermail/chandler-dev/attachments/20040805/01973d31/signature.pgp

More information about the Dev mailing list