Skip to content

XSS via Metadata Title Injection (completeHTMLDocument) #1047

@vc-smoore

Description

@vc-smoore

When both the metadata and completeHTMLDocument options are enabled,
showdown parses YAML-style frontmatter and builds a full HTML document.
The metadata parser in src/subParsers/makehtml/metadata.js escapes &
and " in the metadata values, but doesn't touch < or >:

content = content
  .replace(/&/g, '&amp;')
  .replace(/"/g, '&quot;');

Then in src/subParsers/makehtml/completeHTMLDocument.js, the title
value is inserted directly into <title> tags:

title = '<title>' + globals.metadata.parsed.title + '</title>\n';

Since < and > aren't escaped, you can close the <title> element and
inject arbitrary HTML:

---
title: </title><script>alert(document.cookie)</script>
---
# Hello

Showdown produces:

<!DOCTYPE HTML>
<html>
<head>
<title></title><script>alert(document.cookie)</script></title>
<meta charset="utf-8">
</head>
<body>
<h1 id="hello">Hello</h1>
</body>
</html>

The browser parses </title> as closing the title element, then
executes the <script> block.

This requires a specific combination of options (metadata: true +
completeHTMLDocument: true), which limits the attack surface. But
any application using showdown to render user-supplied markdown into
complete HTML pages is vulnerable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions