Jeff Epler wrote:
...
Imagine that you have: def print_crypted_passwd(name, plaintext, salt="Xx"): crypted = crypt.crypt(plaintext, salt) print _("""%(name)s, your crypted password is %(crypted)s.""") % locals()
and that some crafty devil translates this as msgstr "%(name)s, your plaintext password is %(plaintext). HA HA HA"
i.e., the translator (or other person who can influence the format string) can access other information in the dict you pass in, even if you didn't intend it.
Right. I don't claim that this is a killer problem. I'm actually much more concerned about the usability aspects. But if we can improve security at the same time, then lets.
Personally, I tend to view this as showing that using % locals() is unsanitary. But that means that the problem is in using the locals() dictionary, a problem made worse by making the use of locals() implicit.
If it is done a compile time then the crafty devil couldn't get in the alternate string! On the other hand, if you're doing runtime translation stuff then of course you need to use a runtime function, like "%" or maybe a new "interpol". I am not against the existence of such a thing. I'm against it being the default way to do interpolation. It's like "eval" a compile-time tool that sophisticated users have access to at runtime.
(And under $-substitution, if locals() is implicit, how do I substitute with a dictionary other than locals()?
Well I don't think you should have to, because you could use the "interpol" function (maybe from the "interpol" module). But anyhow, your question has a factual answer and you already gave it!
def print_crypted_passwd(accountinfo): def really_subst(name, crypted): return $"$name, your crypted password is $crypted" print really_subst(accountinfo.name, accountinfo.crypted) or def print_crypted_passwd(accountinfo): name = accountinfo.name crypted = accountinfo.crypted print $"$name, your crypted password is $crypted"
This last one looks very clear and simple to me! What's the problem with it? Still, I don't argue against the need for something at runtime -- as a power tool. Either we could just keep "%" or make a function. Okay, so my proposal for $ doesn't do everything that % does. It was never spec'd to do everything "%" does. For instance it doesn't do float formatting tricks. Paul Prescod