Skip to content

Commit

Permalink
HTML escape YAML after parsing to prevent invalidating YAML string
Browse files Browse the repository at this point in the history
  • Loading branch information
dometto committed Dec 27, 2023
1 parent dbca58f commit 99c67e5
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
21 changes: 20 additions & 1 deletion lib/gollum-lib/filter/yaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def extract(data)
data.gsub!(YAML_FRONT_MATTER_REGEXP) do
@markup.metadata ||= {}
begin
frontmatter = ::YAML.safe_load(sanitize(Regexp.last_match[1]))
frontmatter = sanitize_frontmatter(::YAML.safe_load(Regexp.last_match[1]))
@markup.metadata.merge!(frontmatter) if frontmatter.respond_to?(:keys) && frontmatter.respond_to?(:values)
rescue ::Psych::SyntaxError, ::Psych::DisallowedClass, ::Psych::BadAlias => error
@markup.metadata['errors'] ||= []
Expand All @@ -24,4 +24,23 @@ def extract(data)
def process(data)
data
end

private

def sanitize_frontmatter(obj)
case obj
when Hash
obj.map do |k, v|
[sanitize(k.to_s), sanitize_frontmatter(v)]
end.to_h
when Array
obj.map! do |v|
sanitize_frontmatter(v)
end
when String
sanitize(obj)
else
obj
end
end
end
75 changes: 75 additions & 0 deletions test/filter/test_yaml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
path = File.join(File.dirname(__FILE__), "..", "helper")
require File.expand_path(path)

context "Gollum::Filter::YAML" do
setup do
@page = mock_page
@markup = Gollum::Markup.new(@page)
@filter = Gollum::Filter::YAML.new(@markup)
end

def filter(content)
@filter.process(@filter.extract(content))
end

test 'process yaml' do
markup = <<~EOF
---
Literal Scalar: |
abc
123
Folded Scalar: >
abc
123
Escaped: "abc\n\n123"
---
# Markdown content here
EOF

result = {"Escaped"=> "abc\n" + "123",
"Folded Scalar" => "abc\n" + "123\n",
"Literal Scalar" => "abc\n" + "\n" + "123\n"
}

assert_equal "# Markdown content here\n", filter(markup)
assert_nil @markup.metadata['errors']
assert_equal result, @markup.metadata
end

test 'escape yaml' do
markup = <<~EOF
---
BadStuffInKey<script>bad()</script>: foo
Literal Scalar: |
<script>foo</script>
123
Folded Scalar: >
>abc
<123
Escaped: "abc<script>123</script>"
NestedBadStuff:
Baz:
- [1, "<script>bad()</script>"]
- [1, 2, 3]
---
# Markdown content here
EOF

result = {"Escaped"=> "abc",
"Folded Scalar" => "&gt;abc\n" + "&lt;123\n",
"Literal Scalar" => "\n" + "\n" + "123\n",
"BadStuffInKey" => "foo",
"NestedBadStuff"=> {"Baz"=>[[1, ""], [1, 2, 3]]}
}
filter(markup)
assert_nil @markup.metadata['errors']
assert_equal result, @markup.metadata
end

end
4 changes: 4 additions & 0 deletions test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ def metadata(val={})
val
end

def sanitizer
Gollum::Sanitization.new(Gollum::Markup.to_xml_opts)
end

attr_reader :repo_is_bare
attr_reader :base_path
end
Expand Down

0 comments on commit 99c67e5

Please sign in to comment.