class RuboCop::Cop::Rails::OutputSafety

# “&lt;b&gt;hi&lt;/b&gt; <span>&lt;b&gt;hi&lt;/b&gt;</span>”
# => ActiveSupport::SafeBuffer
safe_join([user_content, “ ”, content_tag(:span, user_content)])
# good
# => ActiveSupport::SafeBuffer “hi <span>hi</span>”
(user_content + “ ” + content_tag(:span, user_content)).html_safe
# bad
# => trusted content&lt;b&gt;hi&lt;/b&gt;
# <%= result %>
# because when rendered in ERB the String will be escaped:
# => String “trusted contenthi
result = out.concat(user_content)
out = “trusted content”
# safe, though maybe not good style
# “<h1>trusted_content</h1>&lt;b&gt;hi&lt;/b&gt;”
# => ActiveSupport::SafeBuffer
out.concat(user_content)
out = “<h1>trusted content</h1>”.html_safe
# good
# => ActiveSupport::SafeBuffer “<h1>trusted_content</h1>hi
out.safe_concat(user_content)
out = “<h1>trusted content</h1>”.html_safe
# bad
# “<li>&lt;b&gt;hi&lt;/b&gt;</li><li>&lt;b&gt;hi&lt;/b&gt;</li>”
# => ActiveSupport::SafeBuffer
safe_join(out)
out << content_tag(:li, user_content)
out << content_tag(:li, user_content)
out = []
# good
# => ActiveSupport::SafeBuffer “<li>hi</li><li>hi</li>”
out.html_safe
out << “<li>#{user_content}</li>”
out << “<li>#{user_content}</li>”
out = “”
# bad
# => ActiveSupport::SafeBuffer “<p>&lt;b&gt;hi&lt;/b&gt;</p>”
content_tag(:p, user_content)
# good
# => ActiveSupport::SafeBuffer “<p>hi</p>”
“<p>#{user_content}</p>”.html_safe
# bad
user_content = “hi
@example
concatenate content and escape it, ensuring its safety.
use ‘safe_join` to join content and escape it and concat to
simply return a SafeBuffer containing the content as is. Instead,
`raw`, and `safe_concat`. These methods do not escape content. They
Checks for the use of output safety calls like `html_safe`,

def looks_like_rails_html_safe?(node)

def looks_like_rails_html_safe?(node)
  node.receiver && node.method?(:html_safe) && !node.arguments?
end

def looks_like_rails_raw?(node)

def looks_like_rails_raw?(node)
  node.command?(:raw) && node.arguments.one?
end

def looks_like_rails_safe_concat?(node)

def looks_like_rails_safe_concat?(node)
  node.method?(:safe_concat) && node.arguments.one?
end

def non_interpolated_string?(node)

def non_interpolated_string?(node)
  node.receiver&.str_type? && !node.receiver.dstr_type?
end

def on_send(node)

def on_send(node)
  return if non_interpolated_string?(node) || i18n_method?(node)
  return unless looks_like_rails_html_safe?(node) ||
                looks_like_rails_raw?(node) ||
                looks_like_rails_safe_concat?(node)
  add_offense(node.loc.selector)
end