On Fri, May 07, 2021 at 01:40:19PM -0600, Nick Humrich wrote:

> PEP 501 already mentions how templates (i-strings?) can solve injection.

I don't think it does. The PEP only mentions the substring "inject" five 
times:

- once in the table of contents;

- twice to describe how f-strings may be vulnerable to code 
  injection attacks;

- once as a section header "Handling code injection attacks"

- and once in that section to describe how third-party libraries can 
  provide "case specific renderers that take care of quoting 
  interpolated values appropriately for the relevant security context".


It seems to me that PEP 501 itself doesn't provide any further 
protection from code injection attacks than do existing solutions.

The PEP gives this simple example:

    os.system(f"echo {message_from_user}")

If `message_from_user` has the value:

    message_from_user = 'pwned; rm /'

then you're going to have a bad time. Your i-strings are no safer:

    os.system(i"echo {message_from_user}")

gives no protection from untrusted input than the f-string version does. 
Merely delaying execution alone doesn't help.

A naive implementation of `os.system` will just run `format()` on the 
interpolation template. Without an appropriate renderer, there's no 
security gain, and PEP 501 explicitly states that it is up to 
third-parties to provide renderers (at least initially).

A serious danger is that people will naively, and wrongly, think that 
they should format the i-string themselves:

    os.system(format(i"echo {message_from_user}"))

and thus defeat any renderers which os.system may provide. And that in 
turn will surely lead people to optimise the code to:

    os.system(f"echo {message_from_user}")

I believe that if you are interested in preventing code injection 
attacks, it would be much better to introduce tainted and untainted 
strings: all non-literal strings are assumed tainted until explicitly 
escaped and flagged as untainted, after which they are considered safe 
to use.

Either that or use the approach favoured by the stdlib: pass a string 
template and a tuple of values which are then quoted before being 
interpolated into the template.

The bottom line here is that I think you are exaggerating the benefits 
of PEP 501 i-strings to "completely remove injection attacks".

Even if i-strings did everything you want, to *completely* remove 
injection attacks would require *all* such functions:

* eval, exec
* os.system
* sql

etc break backwards compatibility by no longer supporting string inputs 
at all, only interpolation template objects. So long as we *can* pass a 
plain old string to such functions, somebody *will* pass strings, and 
some of those will be tainted.



-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DM3SUFWCHVZ7RU2C43TXHS6CQDBVEFRO/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to