On Friday, 30 August 2024 at 12:07:47 UTC, kdevel wrote:
>On Thursday, 29 August 2024 at 14:21:24 UTC, Steven Schveighoffer wrote:
>On Thursday, 22 August 2024 at 19:34:32 UTC, kdevel wrote:
>writeln
should not print unadorned interpolated string expressions.
I find this argument unconvincing.
You can print anything with writeln
. [...]
Not really, e.g. in the case of an object the class name will be printed instead of the potentially dangerous content:
import std.stdio;
class C {
string s;
this (string s)
{
this.s = s;
}
}
void main ()
{
auto c = new C ("<script>alert(-1)</script>");
writeln (c);
}
But it still prints something. I guarantee if someone could have figured out how to make it print all the fields via a runtime interface, this would have happened.
In other words, the expectation is that the toString
value is useful for string representation logging by default. The class name is the best you can do with a runtime-only interface by default, so that's what it is. It wasn't a conscious choice with HTML injection in mind.
In a superior implementation of write(ln) this would simply also not compile. I mean there is a difference between printing the data payload to the output channel and OTOH dumping debug information to the developer.
If Object.toString()
didn't exist, then writeln(someObject)
would by default print the class name via typeid(someObject).toString()
. There is no chance this would be an error by default.
The point of making IES play nice with writeln
is that it is a major expectation of any kind of interpolation setup. People just expect to log interpolated sequences that have their stuff in it.
I don't know if you noticed your own wording: We are expecting to "log" IES data but not to "print" them to the output channel.
Yes, I purposely said log, because that's the intention of writeln
. It's logging the most useful data to the console. For structs, this is all the fields, and the struct name.
For IES, this is what it does for string representation, because that's what people would expect. Use any other language with interpolation, and you will find it does the same thing when logging. Can you imagine what the blowback would be if writeln(i"hello $(name)!");
was an error?
If anything, this draws attention to the pitfalls of CGI in general.
For instance, what if you call a function that logs something to the console? That gets included in your html.
> >[SQL]
Basically, you found just a very narrow example that is unlikely to exist, but indeed might be confusing if an exact series of mistakes are made. Even without IES, a user is equally likely to use writef
to make the same mistake.
With post-1036e D the user has now three equally potent ways to shoot theirself in the foot:
data = "alert (-1)";
writeln ("<script>" ~ data ~ "</script>");
data = "alert (-1)";
writeln (format!"<script>%s</script>" (data));
data = "alert (-1)";
writeln (i"<script>$(data)</script>");
writefln("<script>%s</script>", data);
When you have a footgun cabinet that is almost full, I'm not sure adding one more is something to worry about.
-Steve