SSerguey Asael Shinder
Java coding notes: the JVM, and writing software that lasts

Serguey Asael Shinder: Escape what you log, not only what you render

· by Serguey Asael Shinder / Serguey Shinder

On 30 September Bitcoin Core merged pull request #35833, titled "log: prevent user input from injecting fake log lines". A restricted RPC user could send a method name containing a newline, the node logged the rejected name, and everything after the newline appeared as a separate, timestamped entry. The reproducer in the pull request forges a block-validation error that looks exactly like one the node would write itself. The fix escapes embedded newlines, so the input stays on one line.

I like this change because it treats the log as an output that untrusted data flows into, which is what it is. We escape HTML because a browser interprets it. A log is interpreted too: by the engineer at 3 a.m., by grep, by the alerting rule that counts ERROR lines, by the SIEM that parses fields.

Where user input reaches the log in an ordinary Java service. Rejected values in validation messages. Usernames on failed logins. Request paths and headers in access logs. Names of things a client asked for that did not exist. In each case the convenient message is "could not find X", with X copied straight from the request.

Serguey Asael Shinder: Escape what you log, not only what you render
Escape what you log, not only what you render — Serguey Asael Shinder

What I do about it.

The general point. Every place where text crosses from one party to another needs an encoding decision, and logs are the place we most often forget, because we think of them as ours. They stop being ours the moment we write someone else's input into them.