Hacker News new | past | comments | ask | show | jobs | submit login

I dislike this feature.

The stated use case is to avoid injection attacks. However the primary reason why injection attacks work is that the easiest way to write the code makes it vulnerable to injection attacks. This remains true, and so injection attacks will continue to happen.

Templates offer to improve this by adding interpolations, which are able to do things like escaping. However the code for said interpolations is now located at some distance from the template. You therefore get code that locally looks good, even if it has security mistakes. Instead of one source of error - the developer interpolated - you now have three. The developer forgot to interpolate, the developer chose the wrong interpolation, or the interpolation itself got it wrong. We now have more sources of error, and more action at a distance. Which makes it harder to audit the code for sources of potential error.

This is something I've observed over my life. Developers don't notice the cognitive overhead of all of the abstractions that they have internalized. Therefore over time they add more. This results in code that works "by magic". And serious problems if the magic doesn't quite work in the way that developers are relying on.

Templates are yet another step towards "more magic". With predictable consequences down the road.






I'm not sure I agree with this analysis.

Template.__str__() is equivalent to Template.__repr__(), which is to say that these aren't f-strings in an important sense: you can't get a useful string out of them until you process them in some way.

The expectation is that developers will typically make use of well-established libraries that build on top of t-strings. For instance, developers might grab a package that provides an html() function that accepts Template instances and returns some Element type, which can then be safely converted into a string.

Stepping back, t-strings are a pythonic parallel to JavaScript's tagged template strings. They have many of the same advantages and drawbacks.


In my experience it was precisely when it wasn't abstracted properly that injection attacks became more prevalent, not the other way around.

In PHP, people used to just call mysql_query on a string and all the escaping was done with mysql_escape_string. According to you that nice locality of query construction and sanitization that should've improved security, but my god did it ever not do that.

It was exactly layers of abstractions, moving things far away from the programmer, with prepared statements to ORMs, that meaningfully reduced the number of SQL injection vulnerabilities.

Another example is JavaScript, how many XSS vulnerabilities never happened because of all the shadow dom frameworks? Layers of abstractions like these (JSX,etc) are a major reason we don't see many XSS vulnerabilities nowadays.


> You therefore get code that locally looks good, even if it has security mistakes. Instead of one source of error - the developer interpolated - you now have three.

Could you give examples of this?

> The developer forgot to interpolate

What would this look like? The only way to get dynamic/user input into a template is either through interpolation or concatenation.

Before:

f"..html_str..." + user_provided_str # oops! should have: html_str + sanitize(user_provided_str)

After:

t"...html_template..." + user_provided_str # oops! should have: t"...html_template...{user_provided_str}"

Does this really leave us worse off?

Unless you're referring to something like this:

Before:

html = "love > war" # oops! should have been: html = "love > war"

After:

html = "love > war" # oops! should have been: html = t"love > war"

But then the two scenarios are nearly identical.

> the developer chose the wrong interpolation

What kind of interpolation would be the "wrong interpolation"?

> or the interpolation itself got it wrong.

Isn't that analogous to sanitize(user_provided_str) having a bug?


> Instead of one source of error - the developer interpolated - you now have three. The developer forgot to interpolate, the developer chose the wrong interpolation, or the interpolation itself got it wrong.

The idea is for the interpolation to be provided by the library - just as the library is expected to provide a quoting/escaping/sanitization function today. But now the interpolation function can demand to receive an instance of the new Template type, and raise a `TypeError` if given a pre-formatted string. And that work can perhaps also be rolled into the same interface as the actual querying command. And manually creating a Template instance from a pre-formatted string is difficult and sticks out like a sore thumb (and it would be easy for linters to detect the pattern).

> This is something I've observed over my life. Developers don't notice the cognitive overhead of all of the abstractions that they have internalized. Therefore over time they add more. This results in code that works "by magic". And serious problems if the magic doesn't quite work in the way that developers are relying on.

By this logic, we couldn't have languages like Python at all.


Libraries can enforce only template strings, and properly escape the output. This is already possible in Javascript, and you can completely prevent injection attacks using it. > The developer forgot to interpolate not possible if you enforce only templates

> the developer chose the wrong interpolation Not possible if the library converts from template to interpolation itself

> or the interpolation itself got it wrong Sure, but that would be library code.


It’s kinda like saying += is magic. Yeah the best kind.

That's such a small scope of an addition I don't see the comparison. I suppose overloading arbitrary types with it can sometimes make the actions performed opaque.



Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: