CVE-2026-40890

Denial of Service
Affects
github.com/gomarkdown/markdown; reaches Ingress NGINX Controller via the bundled gomarkdown dependency
in
Ingress NGINX
No items found.
Versions
<v0.0.0-20260411013819-759bbc3e3207 (and Ingress NGINX builds that ship an earlier gomarkdown)

Overview

gomarkdown is a widely deployed Go library for parsing and rendering Markdown. It is the maintained successor to blackfriday and sits as a transitive dependency in many Go projects, including the Ingress NGINX Controller build graph.

An out-of-bounds read vulnerability (CVE-2026-40890) has been identified in the SmartypantsRenderer that gomarkdown ships in the html package. When an input contains a less-than character (<) without a matching greater-than character (>) anywhere in the remainder, the renderer's smartLeftAngle function reads past the end of the input slice. Depending on the slice's capacity, the result is either a one-byte read of adjacent process memory or a runtime panic that terminates the goroutine.

Per OWASP: Buffer Over-read flaws allow an attacker to read memory beyond the allocated bounds of a buffer, and at minimum to crash the receiving service. In network-exposed parsers they are a reliable denial-of-service primitive.

This issue affects all gomarkdown releases prior to commit 759bbc3e3207, including the version that ships in upstream ingress-nginx v1.15.1. HeroDevs has resolved it in NES for Ingress NGINX 1.15.2.

Why this matters for Ingress NGINX deployments

This is a fresh CVE: the upstream patch shipped April 11, 2026, less than two weeks after the Kubernetes project's March 2026 retirement of Ingress NGINX. It is the canonical example of why dependency CVEs keep landing on retired projects: scanners flag the finding, the patch exists upstream in the dependency, and no maintained Ingress NGINX release picks it up.

In a Go binary that processes attacker-influenced markdown anywhere in the request lifecycle (or any auxiliary tooling sharing the build graph), this becomes a denial-of-service primitive on the cluster's edge controller. NES for Ingress NGINX 1.15.2 bumps the gomarkdown/markdown module to the patched version; the container image and Helm chart are drop-in replacements for the upstream v1.15.1 build.

Details

Module Info

  • Product: gomarkdown/markdown Go library; transitive dependency of Ingress NGINX Controller
  • Affected components: smartLeftAngle in html/smartypants.go (lines 367-376), reachable via html.NewSmartypantsRenderer and any HTML renderer constructed with the Smartypants flag
  • Affected versions: all releases prior to v0.0.0-20260411013819-759bbc3e3207; Ingress NGINX builds linking those versions
  • Upstream GitHub repository: <https://github.com/gomarkdown/markdown>
  • Published artifacts (NES):
  • Distribution channels: registry.nes.herodevs.com, HeroDevs Helm chart repository
  • Fixed in:
  • github.com/gomarkdown/markdown commit 759bbc3e3207 (upstream)
  • NES for Ingress NGINX 1.15.2 (April 20, 2026), which bumps the gomarkdown module to the patched pseudo-version

Vulnerability Info

This High-severity vulnerability is found in the Smartypants HTML renderer of gomarkdown/markdown.

Smartypants is a typographic post-processor that converts straight quotes, dashes, and angle brackets into their typographic equivalents. The smartLeftAngle function handles the < character: it scans forward to find the matching > so it can decide whether the input is an HTML tag, an autolink, or literal text that needs entity-encoding. The scan walks the byte slice with an index that the caller advances, and the function is written under the assumption that every < it sees has a > somewhere later in the same buffer.

The bug is that smartLeftAngle does not bound-check the forward scan against the slice length. When the input ends with a stray < (or contains one with no matching > before end-of-input), the index walks past len(buf). If len(buf) equals cap(buf), the next read panics with a slice bounds out of range error. If cap(buf) exceeds len(buf), the read succeeds and returns one byte of whatever happens to live in the underlying array beyond the input, which can include adjacent buffer contents from an earlier request on the same pool.

Threat model for Ingress NGINX clusters: any Go binary in the cluster that renders untrusted Markdown with a Smartypants-enabled HTML renderer is reachable. The trigger is a single < character anywhere in input that is not followed by >. No authentication is required, and no user interaction beyond submitting a comment, message, README, or document. The primary impact is denial of service through panic; the secondary impact is one-byte information disclosure when buffers are pooled (sync.Pool, bufio readers, framework-level body buffers).

When successfully exploited, this vulnerability can lead to:

  • Process or goroutine crash (panic) on hosts that render untrusted Markdown with Smartypants enabled
  • Sustained denial of service through repeated triggering requests
  • Limited adjacent-memory disclosure when the underlying buffer's capacity exceeds its length

Proof Of Concept

A reference reproduction is documented in advisory GHSA-77fj-vx54-gvh7 and the upstream fix at <https://github.com/gomarkdown/markdown/commit/759bbc3e32073c3bc4e25969c132fc520eda2778>. The minimal trigger is:

markdown.ToHTML([]byte("<a"), nil, html.NewRenderer(html.RendererOptions{Flags: html.Smartypants}))

Mitigation

OSS Users

Users of gomarkdown/markdown and upstream Ingress NGINX should apply one of the following mitigations:

  • Upgrade gomarkdown/markdown to commit 759bbc3e3207 or any release that includes it (go get github.com/gomarkdown/markdown@latest dated April 11, 2026 or later).
  • Until upgrade is possible, recover panics in the request handler that wraps Markdown rendering and disable Smartypants for untrusted input by omitting html.Smartypants from the renderer flags.
  • Pre-validate or escape stray < characters before passing input to the renderer if Smartypants must remain on.
  • For Ingress NGINX specifically, no upstream release will rebase against the patched module because the project retired in March 2026. Sign up for post-EOL security support; HeroDevs customers get immediate access to a patched Ingress NGINX build.

NES Customers

HeroDevs Never Ending Support for Ingress NGINX has resolved CVE-2026-40890 in NES for Ingress NGINX 1.15.2 by upgrading the bundled gomarkdown/markdown module to the patched commit. The release ships as a drop-in replacement for upstream ingress-nginx v1.15.1:

  • Pull the patched container image: registry.nes.herodevs.com/neverendingsupport/ingress-nginx-controller:v1.15.1-nes-1.15.2
  • Or upgrade via the public Helm chart: HeroDevs/ingress-nginx --version 0.0.2 (helm-charts documentation)
  • VEX statements ship with the release so scanners that consume OpenVEX or CycloneDX VEX surface the patched status instead of leaving CVE-2026-40890 as an open finding.

Compliance impact

This CVE landed less than two weeks after the upstream Ingress NGINX project retired. It is exactly the kind of finding that compliance frameworks expect to be closed quickly:

  • The EU Cyber Resilience Act's Article 14 reporting obligations begin September 11, 2026; "the upstream project no longer ships fixes" is not a valid answer.
  • DORA's ICT third-party risk requirements have been in force since January 2025.
  • PCI DSS 4.0 expects continuous evidence that components receive security patches.
  • FedRAMP authorizations carry continuous monitoring obligations.

The NES release ships a documented patch trail plus VEX statements that scanners consume programmatically.

Taking Action

If your service renders user-supplied Markdown with Smartypants, upgrade past commit 759bbc3e3207 and verify that the rendering call is wrapped in a panic-recovering handler so that a single malformed input does not crash the worker. For Ingress NGINX deployments specifically, the upstream project will not ship a release that picks up the patched module because it retired in March 2026 and is in dependency-CVE drift. NES for Ingress NGINX 1.15.2 is the patched build for clusters that cannot complete a Gateway API migration before regulatory deadlines. Pull the 1.15.2 image and Helm chart per docs.herodevs.com/ingress-nginx/release-notes.

Credits

  • JulesDT (finder, Datadog Security Research)
  • Datadog Security team (coordination)
  • HeroDevs NES for Ingress NGINX engineering (downstream dependency upgrade and rebuild)

References

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2026-40890
PROJECT Affected
github.com/gomarkdown/markdown; reaches Ingress NGINX Controller via the bundled gomarkdown dependency
Versions Affected
<v0.0.0-20260411013819-759bbc3e3207 (and Ingress NGINX builds that ship an earlier gomarkdown)
NES Versions Affected
Published date
April 29, 2026
≈ Fix date
April 20, 2026
Category
Denial of Service
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Ingress NGINX
Rss feed icon
Subscribe via RSS
or

By clicking “submit” I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.