Live data from Hacker News

A bite of Python

access.redhat.com

61–70 of 168 posts

Re: A bite of Python

#61
post #25
post #9

Earlier quoted context omitted.

Relying on developers to read and remember every bit of documentation for every bit of code is more likely to end up with insecure code compared to introducing sane defaults with an explicit, expressive API.

And the TL;DNR being: developers can't be expected to do a good job. Some of them in fact will do a terrible job. This can be said for every industry involving people.

And the way we handle that is by designing systems to compensate for the fallibility of humans so that the human-computer system is more robust as a whole.

Re: A bite of Python

#62
post #49
post #18

Earlier quoted context omitted.

> It's not an anomaly, but it can be a surprise for people who don't understand what it does. That's almost a tautology though.

The point is that they think they understand it, because most of Python behaves the same in development and production. You see this function called 'assert', it gives the right error at the right time, and all is good. Then you push it to production and it stops throwing errors. Eventually, you read the manual and it tells you that this specific function is ignored in production. This is a surprise because, say, pri…

That only happens if you have different production and development environment settings though -- in which case you should expect the different results.

In this particular case, you compiled your code with "-O", so it's not the "same code" used in production, but code compiled with a different flag. Shouldn't they check what the flag does?

Re: A bite of Python

#63
post #62
post #49

Earlier quoted context omitted.

The point is that they think they understand it, because most of Python behaves the same in development and production. You see this function called 'assert', it gives the right error at the right time, and all is good. Then you push it to production and it stops throwing errors. Eventually, you read the manual and it tells you that this specific function is ignored in production. This is a surprise because, say, pri…

That only happens if you have different production and development environment settings though -- in which case you should expect the different results. In this particular case, you compiled your code with "-O", so it's not the "same code" used in production, but code compiled with a different flag. Shouldn't they check what the flag does?

The developer may be deploying code to a server they didn't configure.

I agree with the way it's done in Python, as it's consistent with most other languages. But the blog post is right to point out to inexperienced developers that the way assert behaves might give them a surprise.

Re: A bite of Python

#64
post #51

Earlier quoted context omitted.

It's so crude that, again, it looks like implementation details having been promoted to specs. Field visibility and name mangling done with very magic underscores just doesn't look right, to me.

> Field visibility It has nothing whatsoever to do with field visibility.

The single leading underscore?

Re: A bite of Python

#65
post #58

Earlier quoted context omitted.

I get full well what it does, but I find the syntax "magic" and not very attractive. Why no special keyword for visibility, proper namespaces etc.? In c++ and likes, I know there's a vtable somewhere, and I get why there must be one for virtual funcs, but I don't want to deal with it directly, it's the compiler job. Same for Python, I know it must prevent fields from getting clobbered when inheriting, but I don't wan…

> Same for Python, I know it must prevent fields from getting clobbered when inheriting, but I don't want to be exposed to its mangling or whatever other mechanism it uses. Python does not prevent anything, it gives the developer a name mangling tool, it's up to the developer whether they want to use it or not. By default, identical names will conflict and you will clobber supertype fields or methods.

Again, that's very Perl-ish, to me. "Here are some tools and tricks, use them to do your own OO if you want--but you can easily bypass it all every time you wish".

Re: A bite of Python

#66
post #56

One Python gotcha that has bitten people in my company a lot: fun_call('string1', 'string2' 'string3') That is, missing commas and subsequent string concatenations can lead to nasty errors. I wish Python didn't nick this from C and would have just enforced the use of + to concat over-length strings, if they need to be split to multiple lines.

I love Python, but I have to agree on this one.

Re: A bite of Python

#67
post #25
post #9

Earlier quoted context omitted.

Relying on developers to read and remember every bit of documentation for every bit of code is more likely to end up with insecure code compared to introducing sane defaults with an explicit, expressive API.

And the TL;DNR being: developers can't be expected to do a good job. Some of them in fact will do a terrible job. This can be said for every industry involving people.

Which is why any sane industry has lots of safety involved. We don't just shrug every time someone gets electrocuted to death and say "they forgot part c page 4 of the operations manual which indicates that the off switch doesn't work on tuesdays".

Re: A bite of Python

#68
I'm sorry but that whole article is just FUD...

> Input function

Yes, in Python 2, input() is a shortcut for eval(raw_input(...)), and documented as such. Obviously that is not a safe way to parse user input, and therefore it has been changed in Python 3. So this has been fixed, but if you don't read the documentation you probably will keep introducing security issues with whatever programming language.

> Assert statement

If you want to effectively protect against a certain condition, raise an exception! Asserts, on the other hand, exist to help debugging (and documenting) conditions that should never occur by proper API usage. Stripping debugging code when optimizing is common practice, not only with Python.

> Reusable integers

First of all, this behavior isn't part of the Python programming language, but an implementation detail, and a feature as it reduces memory footprint. But even when small integers wouldn't be cached, you would still have the same situation when using the is operator on variables holding the same int object. On the other hand, caching all integers could easily cause a notable memory leak, in particular considering that ints in Python 3 (like longs in Python 2) can be as large as memory available. But either way, there is no good reason to check for identify if you want to compare values, anyway.

> Floats comparison

floats in Python use essentially the native "double" type. Hence they have whatever precision, your CPU has for double precision floating point numbers, actually it is specified in IEEE 754. That way floating point numbers are reasonable fast, while as precise as in most other programming languages. However, if that still isn't enough for your use case, Python also comes with the decimal module (for fixed-point decimal numbers) and the fractions module (for infinite precision fractions).

And as for infinity, while one would expect float('infinity') to be larger than any numerical value, the result of comparing a numerical value with a non-numerical type is undefined. However, Python 3 is more strict and raises a TypeError.

> Private attributes

Class-private attributes (those starting with __) exist to avoid conflicts with class-private attributes of other classes in the class hierarchy, or similar accidents. From my experience that is a feature that is rarely needed, even more rarely in combination with getattr()/setattr()/delattr(). But if you need to dynamically lookup class-private attributes you can still do so like hastattr('_classname__attrname'). After all, self.__attrname is just syntactical sugar for self._classname__attrname.

Also note that private attributes aren't meant as a security mechanism, but merely to avoid accidents. That's not specific to Python; in most object-oriented languages it is possible to to access private attributes, one way or another. However, Python tries to be transparent about that fact, by keeping it simple.

> Module injection

Yes, Python looks in a few places for modules to be imported. That mechanism is quite useful for a couple of reasons, but most notably it's necessary to use modules without installing them system-wide. It can only become a security hole if a malicious user has write access to any location in sys.path, but not to the script, importing the modules, itself. I can hardly think about a scenario like that, and even then I'd rather blame the misconfiguration of the server.

> Code execution on import

Yes, just like every other script language, Python modules can execute arbitrary code on import. That is quite expected, necessary, and not limited to Python. Even if module injection is an issue, it doesn't make anything worse, as you you don't necessarily have to run malicious code on module import but could do it with whatever API is being called. But as outlined above, this is a rather theoretical scenario.

> Shell injection via subprocess

Yes, executing untrusted input, is insecure. That is why the functions in Python's subprocess module, by default, expect a sequence of arguments, rather than a string that is parsed by the system's shell. The documentation clearly explains the consequences of using shell=True. So introducing a shell injection vulnerability by accident, in Python, seems less likely than with most other programming languages.

> Temporary files

If anything, Python is as unsecure as the underlying system, and therefore as most other programming languages too. But CWE-377, the issue the author is talking about, isn't particular easy to exploit in a meaningful way, plus it requires the attacker to already have access to the local temporary directory. Moreover, Python's tempfile module encourages the use of high-level APIs that aren't effected.

> Templating engines

The reason jinja2 doesn't escape HTML markup by default is that it is not an HTML template engine, but a general purpose template engine, which is meant to generate any text-based format. Of course, it is highly recommended to turn on autoescaping when generating HTML/XML output. But enforcing autoescaping would break other formats.

Re: A bite of Python

#69
post #46

Earlier quoted context omitted.

It's in their threat model under 'Module injection': > The mitigation is to maintain secure access permissions on all directories and package files in search path to ensure unprivileged users do not have write access to them.

Ok, I see. To be honest I read that as "keep your PYTHONPATH sane". I think that's a bit different from worrying about someone having write access to the source, but still related - point taken.

CVE-2008-5983 (https://bugs.python.org/issue5753) "Untrusted search path vuln... prepends an empty string to sys.path when the argv[0] argument does not contain a path separator"

Check out the "yes"es in the "fixed" column in comment at https://bugs.python.org/msg85966

Re: A bite of Python

#70

Earlier quoted context omitted.

> but it's still a gotcha for the audience this blog post is aimed at. Would be nice if they had a pointer to the reason, however.

Unless the article was updated after your comment: the reason is right there in the article: "However, Python does not produce any instructions for assert statements when compiling source code into optimized byte code (e.g. python -O). That silently removes whatever protection against malformed data that the programmer wired into their code leaving the application open to attacks. The root cause of this weakness is t…

I would argue that one should never use '-O' it also strips doc strings from running code. Not really an `optimization` but they had do something right? One couldn't run __unoptimized__ in production could they?
Post reply on HN