All vulnerabilities
CVE-2026-102941GHSA-cv23-7vc5-jfh7

github.com/gomarkdown/markdown: gomarkdown/markdown IsSafeURL panics on short URLs

gomarkdown github.com/gomarkdown/markdowngoLibraries & packages
CVSS
7.5High
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)0.28%Chance of exploitation activity in the next 30 days, higher than 19% of CVEs. Scored 23 Oct 2026FIRST EPSS
Fixed in0.0.0-20260724235538-61af6e1e6971Fixed versionGitHub
Published16 Oct 2026Updated 16 Oct 2026CVE List

What fixes it

  • 0.0.0-20260724235538-61af6e1e6971github.com/gomarkdown/markdown, goGitHubgo get github.com/gomarkdown/markdown@v0.0.0-20260724235538-61af6e1e6971
  • 0.0.0-20260724235538-61af6e1e6971github.com/gomarkdown/markdown, GoOSVgo get github.com/gomarkdown/markdown@v0.0.0-20260724235538-61af6e1e6971

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

IsSafeURL slices url[:nPath] before checking that len(url) >= nPath, so a URL shorter than a path prefix (0, 1 or 2 bytes) triggers a slice-bounds panic, and this is reached end to end when the html.Safelink hardening flag is enabled and the input contains an empty or very short link destination, giving an unrecoverable crash DoS. Confirmed at HEAD (e08cff8; present since 2022).

The defect

parser/parser.go, IsSafeURL:

func IsSafeURL(url []byte) bool {
    nLink := len(url)
    for _, path := range validPaths {          // "/", "./", "../"
        nPath := len(path)
        linkPrefix := url[:nPath]               // line 789: sliced BEFORE the length guard
        if nLink >= nPath && bytes.Equal(linkPrefix, path) {   // line 790: guard is too late
            ...

url[:nPath] is evaluated before the nLink >= nPath check. When len(url) < nPath and cap(url) < nPath, the slice expression panics. Only the relative-path loop is affected; the adjacent URIs loop is already correctly guarded (the signal that this one deviates, the same signal as the anchor). Input: IsSafeURL("") panics ([:1] cap 0), IsSafeURL(".") panics ([:2] cap 1), IsSafeURL("..") panics ([:3] cap 2), while IsSafeURL("/") returns true. End to end: markdown.ToHTML(input, html.CommonFlags|html.Safelink) with input [x]() panics. Attacker model: (1) any service rendering untrusted Markdown with the html.Safelink flag (the URL-sanitizing hardening flag itself introduces the crash); or (2) any downstream that calls the exported parser.IsSafeURL on a 0/1/2-byte attacker URL, no flag required. No recover() anywhere, so an uncaught crash of the calling goroutine.

Verification

EXECUTED with negative controls. Direct: the empty/1/2-char cases panic with the exact slice-bounds message while "/" returns true. End to end via ToHTML with html.CommonFlags|html.Safelink: [x]() panics, while [x](/), [x](http://example.com), plain text, and [x](javascript:alert(1)) (safely dropped) do not. NOT verified: how many downstream apps enable Safelink or call IsSafeURL directly (the default no-Safelink render path does not reach it).

Suggested fix

Move the slice inside the guard: check nLink >= nPath first, then compute url[:nPath] (or use bytes.HasPrefix(url, path), which is length-safe). One-line change, mirroring the already-correct URIs loop.

Also checked and sound: CVE-2026-40890 (smartypants smartLeftAngle OOB) is fixed; CVE-2024-44337 (list/paragraph infinite loop) is fixed (deep nesting capped at maxNesting=64); default XSS is by design (Safelink/SkipHTML not in CommonFlags).

Tooling

AI assistance was used while investigating. The panic is executed-verified with negative controls (IsSafeURL on empty/./.. panics with a slice-bounds error while "/" returns true; ToHTML with html.Safelink on [x]() panics while valid and javascript: links do not), and I confirmed at HEAD that IsSafeURL computes url[:nPath] before the nLink >= nPath guard.

Text from GitHub Advisory Database

Affected versions 3

  • github.com/gomarkdown/markdown, go< 0.0.0-20260724235538-61af6e1e6971GitHub
  • markdownaffected: < 0.0.0-20260724235538-61af6e1e6971CVE List
  • github.com/gomarkdown/markdown, Gofrom first release, fixed in 0.0.0-20260724235538-61af6e1e6971OSV

References 3