Do not post-process content_for block result with template engine
Since 2.8.0, the content_for block result was post-processed with the template engine. There is no actual need to do so, as content_for is not designed to render output, it is designed to store already rendered output. This post-processing was introduced when support for haml templates was added in 2.8.0.
Post-processing the output with the template engine is generally a no-op for most usage as most output does not contain template metaprogramming characters, which is why this went undetected for so long. However, if a content_for block return value contained unescaped user input, it was probably vulnerable to remote code execution if the default ERB template engine is used, the same as if the user input was passed directly to the render or view method.
Example of a vulnerable usage (assuming automatic escaping is not enabled) would be:
<% content_for :foo do %> User name: <%= request.params['user_name'] %> <% end %>
Such usage is likely vulnerable to cross site scripting unless the content_for output is escaped before being displayed, even without the content_for template post-processing. However, the post-processing turned it from a cross site scripting vulnerability into a remote code execution vulnerability. For non-ERB template engines, whether the post-processing introduced a vulnerability depends on the template engine.
Note that if you were correctly escaping user input in your ERB templates (either automatically or manually), you are unlikely to be vulnerable as the escaping escaped the ERB template metacharacters (< and >). For non-ERB templates, escaping the output may not have mitigated the vulnerability, depending on what metacharacters the template engine uses and whether the escaping will modify them.
Calling content_for with an argument was not vulnerable as no post-processing was done on the argument, it was only done on the block result.