Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
HIGH severity

gomarkdown/markdown IsSafeURL panics on short URLsGHSA-cv23-7vc5-jfh7

HIGHFix: gomarkdown/markdown@61af6e1

GHSA-cv23-7vc5-jfh7 is a high-severity (CVSS 7.5) Out-of-bounds Read vulnerability in github.com/gomarkdown/markdown. A fix is available for github.com/gomarkdown/markdown — see the affected versions and patch details below.

Also known asCVE-2026-102941
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 23, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs19th percentile — riskier than 19% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

GHSA-cv23-7vc5-jfh7 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐹github.com/gomarkdown/markdown

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/gomarkdown/markdownall versions0.0.0-20260724235538-61af6e1e6971go get github.com/gomarkdown/markdown@v0.0.0-20260724235538-61af6e1e6971

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/gomarkdown/markdown, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/gomarkdown/markdown to 0.0.0-20260724235538-61af6e1e6971 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-cv23-7vc5-jfh7 is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

Only components that use gomarkdown/markdown to parse and render externally supplied Markdown are affected by this flaw. Components that bundle this dependency without exercising its URL-sanitization and rendering code during normal operation are not affected.

Workaround published by Red Hat
There is no mitigation for this issue. Affected components should update their github.com/gomarkdown/markdown dependency to a release that includes the upstream fix (commit 61af6e1e6971 or later), which validates URL length before it is sliced in parser.IsSafeURL. --- CME Mitigation Guidance (2026-10-20) --- Disclaimer: The following mitigation solutions are provided as a courtesy, pending the application of an official patch. This content was generated utilizing AI tools in conjunction with data from https://cmetaxonomy.org. Customers are advised to independently evaluate and test these temporary mitigations within their own infrastructure. The highest-value action is to validate URL…
Source: Red Hat security advisory for GHSA-cv23-7vc5-jfh7 (CC BY 4.0)

Frequently Asked Questions

## 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: ```go func IsSafeURL(url []byte) bool { nLink := len(url) for _, path := range validPaths { // "/", "./", "../" nPath := len(path)
O3 Security · Impact-Aware SCA

Is GHSA-cv23-7vc5-jfh7 in your dependencies?

Find it across Go, including transitive dependencies.

gomarkdown/markdown IsSafeURL panics on short URLs