Class: Vangrail::Rails::Markup
- Inherits:
-
Vangrail::Rail
- Object
- Vangrail::Rail
- Vangrail::Rails::Markup
- Defined in:
- lib/vangrail/rails/markup.rb
Overview
Removes markup that does something when the answer is rendered.
An answer is text until a client renders it, and most clients render markdown by pulling in a library that passes raw HTML straight through. At that point a script tag in the answer is a script tag in the page, and the model wrote it because a retrieved document told it to. That is a cross-site scripting bug with a language model in the middle of it, and the fact that the model is the delivery mechanism does not make it a different class of bug.
The application's own sanitiser is the real defence and this does not replace it. What this covers is the case where there is no sanitiser, which is most of them, and where the answer is passed to a renderer that was chosen for how its tables look.
Removes rather than blocks. An answer with a script tag in it is an answer with one bad span, the same as an answer with a credential in it.
Not on by default. A desk whose client renders markdown as text, or which escapes before rendering, does not need it, and a rail that strips markup nobody was going to execute is noise in the result.
Constant Summary collapse
- PATTERNS =
{ # Executes on load. 'script' => /<script\b[^>]*>.*?<\/script>|<script\b[^>]*\/?>/mi, # Loads and executes something else. 'frame' => /<(?:iframe|frame|embed|object|applet)\b[^>]*>(?:.*?<\/(?:iframe|frame|embed|object|applet)>)?/mi, # Runs on an event, which is how a lone img tag becomes an exploit. 'event_handler' => /\son[a-z]{3,20}\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/i, # A scheme that executes rather than fetches. 'active_scheme' => /(?:javascript|vbscript|data)\s*:\s*[^\s"'<>)]+/i, # Rewrites where a form or a link goes, or what the page loads next. 'meta_refresh' => /<meta\b[^>]*http-equiv\s*=\s*["']?refresh["']?[^>]*>/i, 'base_tag' => /<base\b[^>]*>/i, 'form' => /<form\b[^>]*>.*?<\/form>|<form\b[^>]*>/mi, # Styling can position an invisible overlay over the page. 'style_block' => /<style\b[^>]*>.*?<\/style>/mi, }.freeze
Instance Attribute Summary collapse
-
#patterns ⇒ Object
readonly
Returns the value of attribute patterns.
Instance Method Summary collapse
- #cache_key(text, _context) ⇒ Object
- #call(text, _context) ⇒ Object
-
#initialize(patterns: PATTERNS, name: 'markup', sides: [:output]) ⇒ Markup
constructor
A new instance of Markup.
- #language_agnostic? ⇒ Boolean
- #offline? ⇒ Boolean
Constructor Details
Instance Attribute Details
#patterns ⇒ Object (readonly)
Returns the value of attribute patterns.
46 47 48 |
# File 'lib/vangrail/rails/markup.rb', line 46 def patterns @patterns end |
Instance Method Details
#cache_key(text, _context) ⇒ Object
61 62 63 |
# File 'lib/vangrail/rails/markup.rb', line 61 def cache_key(text, _context) text end |
#call(text, _context) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/vangrail/rails/markup.rb', line 65 def call(text, _context) body = text.to_s found = [] cleaned = patterns.reduce(body) do |acc, (label, pattern)| acc.gsub(pattern) do found << label '' end end return pass if found.empty? modify(cleaned, categories: found.uniq, reason: "removed #{found.uniq.join(', ')} from the answer") end |
#language_agnostic? ⇒ Boolean
57 58 59 |
# File 'lib/vangrail/rails/markup.rb', line 57 def language_agnostic? true end |
#offline? ⇒ Boolean
53 54 55 |
# File 'lib/vangrail/rails/markup.rb', line 53 def offline? true end |