Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
18 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
The DisallowedRawHtml extension does not escape a disallowed tag when the tag name is the last thing in the raw HTML. A Markdown line containing just <script is emitted unchanged, and the next block can supply its attributes. With the shipped GFM defaults this allows stored XSS by anyone who can post Markdown. Details DisallowedRawHtmlRenderer escapes tags with this regex: The trailing character class requires one character after the tag name. The block parser does not: RegexHelper::PARTIALHTMLBLOCKOPEN accepts end of line after a tag name, so <script alone opens an HTML block. Because a rendered HtmlBlock has no trailing newline, the regex has nothing to match and the < passes through. In the browser the newline is still present, so the tag name terminates there and whatever follows becomes attributes. This is the same filter that GHSA-4v6x-c7xx-hw9f fixed in 2.8.1. That fix widened the character class but still requires one character, so this case was not covered.…
Recommended action: Upgrade to 2.10.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
league/commonmark's GitHub Flavored Markdown Table extension registers TableStartParser as a block-start parser. While a paragraph is the active block, the core block parser calls TableStartParser::tryStart() on every non-blank line. Its first action fetches the entire growing paragraph buffer via getParagraphContent() and runs strpos($paragraph, '|') across all of it. For a paragraph of M pipe-free lines, line k rescans about k lines of buffer, so total work is 1+2+...+M, which is O(M^2). An unauthenticated user who submits a single large paragraph of pipe-free lines that do not begin with a letter (see Attack Chain) to any service that converts untrusted Markdown with GithubFlavoredMarkdownConverter (or any environment that enables TableExtension) drives seconds to tens of seconds of single-core CPU that grows quadratically with body size, enough to exhaust worker processes and deny service. Root Cause The GFM table detector performs a per-line "quick check" against the…
Recommended action: Upgrade to 2.10.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact AttributesExtension ships with the library but must be explicitly registered on the Environment; it is not included in CommonMarkConverter, GithubFlavoredMarkdownConverter, or GithubFlavoredMarkdownExtension. Applications that do not register AttributesExtension are not affected by this advisory. Two paths in the extension re-process every attribute a node has already collected each time another attribute is applied to it. When the attributes carry distinct names, the collected set grows by one on every step and is walked again in full, so a run of n attributes costs O(n²). 1. Attribute nodes resolving to a common target (affected from 1.5.0). AttributesListener::processDocument() merges each attribute node into the set accumulated for its target, then filters the result. Both operations traverse that entire set: AttributesHelper::mergeAttributes() rebuilds it with arraymerge(), and AttributesHelper::filterAttributes() matches a regular expression against every name in it. A…
Recommended action: Upgrade to 2.10.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact Two first-party extensions contain quadratic parsing paths. Both ship with the library but must be explicitly registered on the Environment; neither is included in CommonMarkConverter, GithubFlavoredMarkdownConverter, or GithubFlavoredMarkdownExtension. Applications that do not register SmartPunctExtension or AttributesExtension are not affected by this advisory. 1. SmartPunctExtension — quote replacement recopies the whole text node (affected from 2.0.0). ReplaceUnpairedQuotesListener converts each unpaired Quote node back to a Text node and merges it into its neighbours via AdjacentTextMerger. The merge reads the left node's literal into a local variable, appends to that variable, and writes it back — and because the read aliases the node's string, every append copies the entire accumulated literal rather than only the bytes added. The listener runs this once per surviving unpaired quote against the same continuously growing text node, so the same buffer is fully re-copied a…
Recommended action: Upgrade to 2.9.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The AttributesExtension documents a security guarantee: Note: Attributes starting with on (e.g. onclick or onerror) are capable of executing JavaScript code and are therefore never allowed by default. You must explicitly add them to the allow list if you want to use them. — docs/2.x/extensions/attributes.md Prefixing the attribute name with a single U+000C FORM FEED byte defeats that guarantee. {<FFonclick="alert(1)"} passes through AttributesHelper::filterAttributes() untouched and is written verbatim into the output, where browsers parse it as a genuine onclick handler. The same prefix defeats the allowunsafelinks check, letting a javascript: URI through on href / src even when allowunsafelinks is false. This bypasses the fix shipped in the 2.7.0 security release ("Fix XSS in AttributesExtension", 43207253ea5f14867c77c697cd3838c446cadcea), which added filterAttributes() for the express purpose of blocking these attributes. Throughout this report <FF denotes a literal U+000C…
Recommended action: Upgrade to 2.9.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact Affected versions of league/commonmark perform super-linear work on three independent parsing paths, all of which are reachable on a stock new CommonMarkConverter() with default configuration and no extensions registered. Each trigger fits on a single line of input, so no complex Markdown structure is required. The three paths were introduced at different times. This advisory's version range is their union; the individual ranges are: | Path | Affected from | Affected through | |---|---|---| | 1. Fenced code block detection | 0.6.0 | 2.9.0 | | 2. Reference link label lookup | 0.6.0 | 2.9.0 | | 3. Emphasis / strikethrough delimiters (, , ~) | 2.6.0 | 2.9.0 | | 3. Highlight delimiters (=) | 2.9.0 | 2.9.0 | 1. Fenced code block detection — quadratic, affected from 0.6.0. FencedCodeStartParser matches the following pattern: The lookahead enforces the CommonMark rule that a backtick fence's info string may not itself contain a backtick, but neither the lookahead nor the backtick run…
Recommended action: Upgrade to 2.9.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact XmlRenderer pretty-prints XML by emitting depth-proportional indentation whitespace for every opening and closing tag. For a tree of depth n, the indentation alone sums to O(n²) bytes of output (and corresponding memory), reachable through MarkdownToXmlConverter — e.g. strrepeat(' ', $depth) . "x\n", a single line of nested blockquotes — or through a direct XmlRenderer::renderDocument() call on an attacker-influenced AST. This affects applications that convert untrusted Markdown to XML, which is an opt-in output path. The parser's maxnestinglevel bounds the depth of parser-created trees, but its default is high enough to reach damaging sizes, can be raised by the host application, and does not constrain custom or programmatically built ASTs handed straight to the renderer. The result is a memory / output-size amplification rather than a hard crash, which is why this issue is rated Medium rather than High. No confidentiality or integrity impact. XML rendering was introduced in…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact UniqueSlugNormalizer::normalize() makes each slug document-unique by searching for an unused numeric suffix, but restarts that search from 1 on every collision. The k-th heading that collapses to the same base slug performs k−1 array lookups, so K colliding slugs cost Σ(k−1) = O(K²). An attacker can force every heading onto a single base slug trivially — many empty ATX headings, identical heading text, or punctuation-only headings that normalize to the empty string. The path is reached whenever the shared slug normalizer runs over attacker-controlled text. That happens when HeadingPermalinkExtension is registered (its HeadingPermalinkProcessor normalizes every heading), independently through FootnoteExtension (its AnonymousFootnoteRefParser normalizes every ^[label] reference), and on any TableOfContentsExtension site (which requires HeadingPermalinkExtension to be co-registered). The default slugnormalizer/unique setting (UniqueSlugNormalizerInterface::PERDOCUMENT)…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact The Footnote extension records one backref per footnote reference and then appends the entire backref list for every footnote definition block in the document, without ever de-duplicating or removing repeated definitions of the same label (GatherFootnotesListener, populated by NumberFootnotesListener). A document that references a single label N times and also supplies N duplicate [^a]: definitions of that label therefore produces N × N FootnoteBackref nodes, so output size, parse time, and peak memory are all O(N²). Reaching the vulnerable path requires FootnoteExtension to be registered on the Environment. This is opt-in, but is a commonly enabled GFM-style feature; no other non-default configuration is required. An unauthenticated attacker can expand a ~10 KB request into a ~62 MB HTML response, ~3 s of CPU, and ~440 MB of peak memory — enough to OOM-kill a default 128 MB PHP worker and deny service. Availability impact only; no confidentiality or integrity effect. The…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact With the Attributes extension enabled, AttributesListener::findTargetAndDirection() resolves each attribute node's target by walking outward through its siblings. For a run of N adjacent inline attribute blocks placed at the start of a block (with nothing to their left), each node scans the entire sibling list to the far-right end before giving up and falling back to the parent. Each resolution is therefore Θ(N) and the whole run is Θ(N²). Reaching the path requires AttributesExtension (opt-in, but first-party: League\CommonMark\Extension\Attributes\AttributesExtension). No other configuration matters — the quadratic walk runs unconditionally during parsing and is not gated by the attributes/allow allow-list, the on hardening added in 2.7.0, or allowunsafelinks. An unauthenticated attacker can submit a ~32 KB input ({#a} repeated 8,000 times) that takes over 5 seconds to convert, with time growing quadratically in input length — a cheap denial of service. Availability impact…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact Affected versions of league/commonmark can have quadratic time complexity when parsing specially crafted Markdown lines. In practical terms, doubling the length of an affected line can make the parser perform roughly four times as much work. The parser identifies locations using character positions, but regular-expression matches report byte positions. These positions differ when a UTF-8 character uses more than one byte. Several parsing paths repeatedly rescan growing portions of the line to translate between the two positions. The Autolink extension can also copy and validate the remaining line at every URL-like prefix. In current 2.x releases, a single non-ASCII character anywhere on a line can place that whole line on the slower multibyte path. An attacker can combine it with a long run of leading whitespace or repeated Markdown punctuation, causing increasingly large rescans. When the Autolink extension is enabled, repeated URL-like prefixes provide another trigger, even…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The AttributesExtension's href/src unsafe-link filter (AttributesHelper::filterAttributes()) can be bypassed by embedding control bytes in a javascript: URL that browsers discard before parsing the scheme. Two variants: - Tab/newline inside the scheme — a literal ASCII TAB (0x09), CR (0x0D), or LF (0x0A), e.g. java<TABscript:alert(1). Per the WHATWG URL Standard's "basic URL parser" step 3, browsers "remove all ASCII tab or newline from input". - Leading C0 controls — e.g. <0x01javascript:alert(1). Per step 1 of the same algorithm, browsers remove any leading or trailing C0 control or space. (A leading space alone does not bypass, because parseAttributes() already trim()s the value; other C0 bytes are not trimmed.) The filter is a literal anchored-prefix regex (RegexHelper::isLinkPotentiallyUnsafe() / REGEXUNSAFEPROTOCOL) that matches neither obfuscated form, so in both cases the browser still executes javascript:alert(1). This is confirmed reproducible even with…
Recommended action: Upgrade to 2.9.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact The DomainFilteringAdapter in the Embed extension is vulnerable to an allowlist bypass due to a missing hostname boundary assertion in the domain-matching regex. An attacker-controlled domain like youtube.com.evil passes the allowlist check when youtube.com is an allowed domain. This enables two attack vectors: - SSRF: The OscaroteroEmbedAdapter makes server-side HTTP requests to the embed URL via the embed/embed library. A bypassed domain filter causes the server to make outbound requests to an attacker-controlled host, potentially probing internal services or exfiltrating request metadata. - XSS: EmbedRenderer outputs the oEmbed response HTML directly into the page with no sanitization. An attacker controlling the bypassed domain can return arbitrary HTML/JavaScript in their oEmbed response, which is rendered verbatim. Any application using the Embed extension and relying on alloweddomains to restrict domains when processing untrusted Markdown input is affected. Patches This…
Recommended action: Upgrade to 2.8.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact The DisallowedRawHtml extension can be bypassed by inserting a newline, tab, or other ASCII whitespace character between a disallowed HTML tag name and the closing . For example, <script\n would pass through unfiltered and be rendered as a valid HTML tag by browsers. This is a cross-site scripting (XSS) vector for any application that relies on this extension to sanitize untrusted user input. All applications using the DisallowedRawHtml extension to process untrusted markdown are affected. Applications that use a dedicated HTML sanitizer (such as HTML Purifier) on the rendered output are not affected. Patches Fixed in 2.8.1. The regex character class [ \/] was changed to [\s\/] to match all whitespace characters that browsers accept as valid tag name terminators. Workarounds - Set the htmlinput configuration option to 'escape' or 'strip' to disable all raw HTML, though this is a broader restriction than the DisallowedRawHtml extension provides. - Pass the rendered HTML through…
Recommended action: Upgrade to 2.8.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Cross-site scripting (XSS) vulnerability in the Attributes extension of the league/commonmark library (versions 1.5.0 through 2.6.x) allows remote attackers to insert malicious JavaScript calls into HTML. Details The league/commonmark library provides configuration options such as htmlinput: 'strip' and allowunsafelinks: false to mitigate cross-site scripting (XSS) attacks by stripping raw HTML and disallowing unsafe links. However, when the Attributes Extension is enabled, it introduces a way for users to inject arbitrary HTML attributes into elements via Markdown syntax using curly braces. As a result, even with the secure configuration shown above, an attacker can inject dangerous attributes into applications using this extension via a payload such as: Which results in the following HTML: Which causes the JS to execute immediately on page load. Patches Version 2.7.0 contains three changes to prevent this XSS attack vector: - All attributes starting with on are considered…
Recommended action: Upgrade to 2.7.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact Several polynomial time complexity issues in league/commonmark may lead to unbounded resource exhaustion and subsequent denial of service. Malicious users could trigger that inefficient code with carefully crafted Markdown inputs that are specifically designed to ensure the worst-case performance is reached. Sending multiple such requests in parallel could tie up all available CPU resources and/or PHP-FPM processes, leading to denial of service for legitimate users. Patches These vulnerabilities have been patched in version 2.6.0. All users on older versions are highly encouraged to upgrade as soon as possible. Workarounds If you cannot upgrade, you may be able to mitigate the issues by: - Setting very low memorylimit and maxexecutiontime PHP configurations to prevent runaway resource usage - Implementing rate-limiting, bot protection, or other approaches to reduce the risk of simultaneous bad requests hitting your site - Limiting the size of inputs fed into this library…
Recommended action: Upgrade to 2.6.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Cross-site scripting (XSS) vulnerability in the PHP League CommonMark library versions 0.15.6 through 0.18.x before 0.18.1 allows remote attackers to insert unsafe URLs into HTML (even if allowunsafelinks is false) via a newline character (e.g., writing javascript as javascri%0apt).
Recommended action: Upgrade to 0.18.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
CVE-2019-10010 Impact In league/commonmark 0.18.2 and below, malicious users can insert double-encoded HTML entities into their Markdown like this: This library would (correctly) unescape the & entity to & during the parsing step. However, the renderer step would fail to properly re-escape the resulting : string, thus producing the following malicious HTML output: Browsers would interpret : as a : character and allow the JS to be executed when the link is clicked. This vulnerability was present in the upstream library this project was forked from and therefore exists in all prior versions of league/commonmark. Solution The new 0.18.3 release mirrors the fix made upstream - we no longer attempt to preserve entities when rendering HTML attributes like href, src, title, etc. The $preserveEntities parameter of Xml::escape() is therefore no longer used internally, so it has been deprecated and marked for removal in the next major release (0.19.0). Credits - Mohit Fawaz for…
Recommended action: Upgrade to 0.18.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.