cebe / cebe/markdown

XSS via quote injection in renderEmail() (email autolink)

Open Beginner friendly
#192 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
HTML
Stars
1k
Forks
137
PR merge metrics
No merged PRs in 30d

Description

`renderEmail()` in `inline/LinkTrait.php` (lines 194-198, unchanged since 2014-10-10) escapes the parsed email address with `htmlspecialchars(..., ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8')`, which does **not** escape double-quote characters, and then interpolates it into a double-quoted HTML href attribute:

```php
protected function renderEmail($block)
{
$email = htmlspecialchars($block[1], ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
return "$email";
}
```

The email autolink regex in `parseLt()` (`/^<([^\s>]*?@[^\s]*?\.\w+?)>/`) allows `"` in the local part. Input `<"onmouseover=alert(1)//@x.y>` is parsed as an email autolink and rendered as:

```

"onmouseover=alert(1)//@x.y


```

Verified with **html5lib** (faithful HTML5 tokenizer): the browser parses this as `` — a **live `onmouseover` event handler**. On hover, `alert(1)` executes.

## Why this is distinct from CVE-2018-1000874

That CVE (DISPUTED) was about fenced-code-block raw HTML passthrough. This bug is **not** raw HTML passthrough: `parseLt()` routes `<...@x.y>` to `renderEmail()` *before* the raw-HTML fallback (`parseInlineHtml`). The broken HTML is generated by the library from a markdown-syntax autolink, not passed through from user HTML. I acknowledge the maintainer's documented position that output should be filtered with HTML Purifier; this is offered as an escaping defect the library itself introduces.

## Affected

- `Markdown`, `MarkdownExtra`, `GithubMarkdown` (shared `LinkTrait`)
- Versions: ≥1.1.2 through 1.2.1 and master (`2b2461b`)
- No fix exists.

## CVSS v3.1

5.8 Medium — `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N`

Constraint: the injected portion cannot contain whitespace (regex excludes `\s`), so the practical payload is interaction-required (`onmouseover`); no no-interaction payload found.

## Suggested fix

```php
protected function renderEmail($block)
{
$email = htmlspecialchars($block[1], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
return "
$email";
}
```

## Reproduction

```php
parse('<"onmouseover=alert(1)//@x.y>'), PHP_EOL;
```

Output:
```

"onmouseover=alert(1)//@x.y


```

Independent discovery during a security audit. Verified novel: OSV empty, GitHub Advisory DB empty, no prior issue/comment mentions `renderEmail`/`mailto`/`ENT_NOQUOTES`.

Contributor guide

Open the contributing guide

Research direction

Start in inline/LinkTrait.php at renderEmail() and trace how parseLt() sends email autolinks there. Reproduce the quoted local-part input from the issue, then add coverage for the generated HTML. Done means quotes in an autolink cannot become HTML attribute syntax or an event handler, while ordinary email autolinks still render correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.