[Ruby] How to write when you want to keep line breaks while avoiding XSS with Rails

less than 1 minute read

Output the following character strings containing Script tags in various ways and compare the differences.

@hoge


<script>
  alert('you are an idiot');
</script>

Output as is

erb


<%= @hoge %>

output


<script> alert('you are an idiot'); </script>

result

XSS can be avoided, but line breaks and spaces are not reflected

html_safe

erb


<%= @hoge.html_safe %>

output


Script is executed!

result

Triggers XSS. Despite its name, html_safe is not safe at all.

simple_format(@hoge, sanitize: true)

erb


<%= simple_format(@hoge, sanitize: true) %>

output


alert('you are an idiot');

result

The script tag is deleted

h(@hoge)

erb


<%= h(@hoge) %>

output


<script> alert('you are an idiot'); </script>

result

XSS can be avoided, but line breaks and spaces are not reflected

simple_format(h(@hoge))

erb


<%= simple_format(h(@hoge)) %>

output


<script>
alert('you are an idiot');
</script>

result

XSS does not occur. The script tag is escaped and line breaks are retained. Only the space after the line break is not reflected.

Remarks

If you want to reflect line breaks, simple_format(h(@hoge) seems good.