Update dependency league/commonmark to v2.10.0 [SECURITY] - #890
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
Contributor
Author
Branch automerge failureThis PR was configured for branch automerge. However, this is not possible, so it has been raised as a PR instead.
|
|
Hello 👋 here is the most recent benchmark result:
This comment gets update everytime a new commit comes in! |
renovate
Bot
deleted the
renovate/packagist-league-commonmark-vulnerability
branch
September 5, 2026 05:51
renovate
Bot
force-pushed
the
renovate/packagist-league-commonmark-vulnerability
branch
2 times, most recently
from
September 5, 2026 09:43
4c0a615 to
4811518
Compare
| datasource | package | from | to | | ---------- | ----------------- | ----- | ------ | | packagist | league/commonmark | 2.9.0 | 2.10.0 | Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
renovate
Bot
force-pushed
the
renovate/packagist-league-commonmark-vulnerability
branch
from
September 14, 2026 17:18
4811518 to
3a595e2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.9.0→2.10.0Warning
Some dependencies could not be looked up. Check the Dependency Dashboard for more information.
league/commonmark XSS:
on*event-handler filter inAttributesExtensionbypassed with a U+000C form feedGHSA-f8fg-pg57-v4j8
More information
Details
Summary
The
AttributesExtensiondocuments a security guarantee:Prefixing the attribute name with a single U+000C FORM FEED byte defeats that guarantee.
{<FF>onclick="alert(1)"}passes throughAttributesHelper::filterAttributes()untouched and iswritten verbatim into the output, where browsers parse it as a genuine
onclickhandler.The same prefix defeats the
allow_unsafe_linkscheck, letting ajavascript:URI through onhref/srceven whenallow_unsafe_linksisfalse.This bypasses the fix shipped in the 2.7.0 security release ("Fix XSS in AttributesExtension",
43207253ea5f14867c77c697cd3838c446cadcea), which added
filterAttributes()for the expresspurpose of blocking these attributes.
Throughout this report
<FF>denotes a literal U+000C byte ("\x0C"in PHP). It is invisible inrendered text, so all payloads below are written with PHP escape sequences to stay unambiguous.
Details
Three behaviours combine.
1.
\x0Csurvives the parser'strim().AttributesHelper::SINGLE_ATTRIBUTEbegins with\s*, andCursor::match()returns$matches[0][0]— the entire match, including that leading whitespace. The result is cleanedwith PHP's
trim():PCRE
\smatches\x0C, but PHP's defaulttrim()charlist is" \t\n\r\0\x0B"— it includesthe vertical tab
\x0Bbut not the form feed\x0C. The byte is therefore consumed by theregex, retained in the returned match, and not stripped. It ends up inside the attribute name:
\x0Cis the only byte with this property: every other character the HTML5 tokenizer treats aswhitespace (
\x09,\x0A,\x0D,\x20), plus\x0B, is in PHP's trim charlist. The PoCincludes a
\x0Bcase as a control, and it is correctly stripped.2. The filter's string comparisons miss it.
filterAttributes()compares the raw name against literal strings:3. The renderer never escapes attribute names.
Because the HTML5 tokenizer treats
\x0Cas whitespace between attributes, the browser readsthe name as plain
onclick.PoC
Full observed output (
\x0Cshown escaped; it is a literal single byte in the real output):hello {onclick="alert(1)"}<p>hello</p>hello {\x0Conclick="alert(1)"}<p \x0Conclick="alert(1)">hello</p>hello {\x0Bonclick="alert(1)"}<p>hello</p>[click](javascript:alert(1))<p><a>click</a></p>[click](https://example.com){\x0Chref="javascript:alert(1)"}<p><a \x0Chref="javascript:alert(1)" href="https://example.com">click</a></p>{\x0Conerror="alert(1)"}<p><img \x0Conerror="alert(1)" src="…" alt="x" /></p># heading+ newline +{\x0Conclick="alert(1)"}<h1 \x0Conclick="alert(1)">heading</h1>In case E the injected
hrefprecedes the legitimate one. Per the HTML5 duplicate-attribute rulethe first occurrence wins, so the
javascript:URI is the one the browser actually uses.Browser confirmation. Loading the library's unmodified output in Chrome for Testing 148:
The
onerrorcase executes with no user interaction — rendering the attacker's Markdown issufficient.
Verified against git HEAD (
f966b17a) and against tag2.9.0, on PHP 8.5.8.Impact
Stored cross-site scripting in any application that renders untrusted Markdown with
AttributesExtensionenabled andattributes.allowleft at its default[]— even when theapplication has followed every hardening step in
docs/2.x/security.md(
html_input => 'escape',allow_unsafe_links => false,max_nesting_level => 100).Consequences are the usual for stored XSS: session and cookie theft, actions performed as the
viewing user, and account takeover where the host application permits it. Because the payload can
be attached to an image (
onerror), it fires on page load without requiring the victim tointeract with anything.
The affected configuration is the extension's default:
attributes.allowdefaults to[], andthe documentation describes that default as safe with respect to
on*attributes.Workaround for users
Setting an explicit allow list takes the other branch of
filterAttributes(), which drops theform-feed name because it is not in the list:
Verified:
hello {\x0Conclick="alert(1)"}then renders as<p>hello</p>.Suggested fix
The narrow fix is to add
\x0Cto the trim charlist atAttributesHelper.phplines 62, 89, 90and 94. That closes this instance but leaves the shape of the problem in place.
A more durable fix is to reject anything that is not a well-formed attribute name in
filterAttributes(), reusing the constant the parser already defines (RegexHelperis alreadyimported in that file):
As defence in depth,
HtmlElement::__toString()could validate or escape$key. It currentlytrusts its callers to supply safe attribute names, and
filterAttributes()is the only thingstanding between that method and user-supplied input.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
league/commonmark: Denial of service in the SmartPunct and Attributes extensions
GHSA-jjv6-8j6v-6j52
More information
Details
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 inCommonMarkConverter,GithubFlavoredMarkdownConverter, orGithubFlavoredMarkdownExtension. Applications that do not registerSmartPunctExtensionorAttributesExtensionare not affected by this advisory.1.
SmartPunctExtension— quote replacement recopies the whole text node (affected from 2.0.0).ReplaceUnpairedQuotesListenerconverts each unpairedQuotenode back to aTextnode and merges it into its neighbours viaAdjacentTextMerger. 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 linear number of times.A 1.2 MB document of alternating text segments and apostrophes takes 34.9 seconds to convert, against 0.069 seconds for the same input with the extension not registered.
Hardened configuration makes this worse rather than better:
QuoteParserappends theQuotenode to the AST before pushing it onto the delimiter stack, somax_delimiters_per_lineremoves the quote-pairing work while leaving every node the listener must process.2.
AttributesExtension— block-level attribute runs re-scan their siblings (affected from 1.5.0).AttributesListener::findTargetAndDirection()walks the entire remaining sibling chain for every block-levelAttributesnode whose target is the following node. The backward half of that walk returns immediately for such nodes, and the forward half stops only at a sibling that is not itself an attributes node — which a contiguous run never provides — so a run of k nodes costs k(k-1)/2 steps.An input placing each
{#a}on its own line, with a single reference definition to keep the run contiguous, takes 28.4 seconds at 16,000 attribute blocks while producing zero bytes of output.This is the block-level counterpart of GHSA-g2gp-3wwq-f4ph, patched in 2.9.0. That fix is incomplete: the early break it introduced is guarded on the node being an
AttributesInline, so block-levelAttributesnodes still re-scan. Applications that upgraded to 2.9.0 specifically to address GHSA-g2gp-3wwq-f4ph remain exposed to this variant.3.
AttributesExtension— class lists are rebuilt on every merge (affected from 1.5.0).AttributesHelper::mergeAttributes()round-trips the accumulated class list throughexplodeandimplodeon each merge. An#idattribute assigns a scalar and skips the branch entirely, but a.classattribute appends to an array which is then imploded to a string, written to the target node, and read back on the next iteration — so the ith merge pays a cost proportional to i three separate times.{.c}repeated 32,000 times takes 33.5 seconds, against 0.26 seconds for byte-identical input using{#a}— a 130x gap that widens with input size. Both the inline and the block-level attribute paths are affected.Overall impact. An unauthenticated attacker who can submit Markdown to an affected application can consume disproportionate CPU time with a comparatively small request, occupying PHP workers and preventing legitimate requests from completing. The impact is limited to availability: no data is disclosed, rendered output is unchanged, and no rendering restriction is bypassed.
No library-level configuration gates any of these paths. For the Attributes extension in particular, neither the
attributes/allowallow-list nor theon*event-handler hardening added in 2.7.0 has any effect, because the expensive work happens while parsing and resolving the AST, before any attribute filtering or rendering takes place.Patches
The issues are patched in
2.9.1and later:AttributesListenernow records the runs it has already walked, so each contiguous run of block-level attribute nodes is scanned once rather than once per node.mergeAttributes()repeatedly; the listener holds pending attributes and joins them in a single pass.The SmartPunct path affects
2.0.0through2.9.0. The Attributes paths affect1.5.0through2.9.0, including releases that already contain the 2.9.0 fix for GHSA-g2gp-3wwq-f4ph. The 1.x release line is no longer supported, so its users must upgrade to2.9.1or later.Workarounds
If you cannot upgrade immediately:
SmartPunctExtensionorAttributesExtensionwhen converting untrusted Markdown. This fully removes the affected paths.Restricting conversion to trusted users, applying strict execution-time limits, and rate-limiting requests reduce exposure but are not substitutes for upgrading. Configuration options including
attributes/allow,max_delimiters_per_line,max_nesting_level,html_input, andallow_unsafe_linksdo not mitigate these issues.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
league/commonmark: Denial of service via distinctly-named attributes in the Attributes extension
GHSA-8rr7-cvq3-gmfh
More information
Details
Impact
AttributesExtensionships with the library but must be explicitly registered on theEnvironment; it is not included inCommonMarkConverter,GithubFlavoredMarkdownConverter, orGithubFlavoredMarkdownExtension. Applications that do not registerAttributesExtensionare 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 witharray_merge(), andAttributesHelper::filterAttributes()matches a regular expression against every name in it. A run of attribute nodes sharing one target therefore re-walks a set that grows by a key per node.Two input shapes reach this path: adjacent inline attributes at the start of a block (
{a0="v"}{a1="v"}…, where quoting the values is what keeps them separate — an unquoted value swallows the}{that follows it), and a chain of attribute blocks held at their default target by reference definitions ({a0=v}/[a]: u/{a1=v}/[a]: u/ …).256 KB of adjacent inline attributes takes 20.0 seconds to convert, against 0.09 seconds once patched.
2. Consecutive attribute-block lines (affected from 2.0.0).
AttributesBlockContinueParser::tryContinue()merges each continuation line into the block's accumulated attributes, again rebuilding the whole set on every line. One distinct attribute per line ({a0=v}/{a1=v}/ …) grows it by a key each time.256 KB of such lines takes 1.9 seconds to convert while producing zero bytes of output, against 0.08 seconds once patched.
Relationship to GHSA-jjv6-8j6v-6j52. The fix released in 2.9.1 for that advisory made the
classattribute cheap to accumulate, but left every other attribute name on the original path. Applications that upgraded to 2.9.1 or 2.9.2 remain exposed to this variant.Overall impact. An unauthenticated attacker who can submit Markdown to an affected application can consume disproportionate CPU time with a comparatively small request, occupying PHP workers and preventing legitimate requests from completing. The impact is limited to availability: no data is disclosed, rendered output is unchanged, and no rendering restriction is bypassed.
Patches
The issue is patched in
2.10.0. Both paths now fold each node — or each line — into the accumulated attributes at a cost proportional to that node or line alone, rather than re-merging and re-filtering everything gathered so far. Rendered output is unchanged, down to the order in which attributes appear.The listener path affects
1.5.0through2.9.2. The continuation-line path affects2.0.0through2.9.2. The 1.x release line is no longer supported, so its users must upgrade to2.10.0or later.Workarounds
If you cannot upgrade immediately:
AttributesExtensionwhen converting untrusted Markdown. This fully removes both paths.The
attributes/allowallow-list added in 2.7.0 is not a mitigation. A non-empty allow-list happens to bound the first path, because unlisted names are discarded before they accumulate, but it does nothing for the second: continuation lines are merged while parsing, before any filtering takes place.Restricting conversion to trusted users, applying strict execution-time limits, and rate-limiting requests reduce exposure but are not substitutes for upgrading.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
league/commonmark: Denial of service via crafted code fences, reference links, and emphasis delimiters
GHSA-j8pm-gj4c-rq4x
More information
Details
Impact
Affected versions of
league/commonmarkperform super-linear work on three independent parsing paths, all of which are reachable on a stocknew 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:
0.6.02.9.00.6.02.9.0*,_,~)2.6.02.9.0=)2.9.02.9.01. Fenced code block detection — quadratic, affected from 0.6.0.
FencedCodeStartParsermatches 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 it guards is atomic or possessive. On a line consisting of a long backtick run, filler text, and a single trailing backtick, the quantifier gives back one character at a time and re-runs the lookahead across the remainder of the line on every candidate fence length.
A 320 KB single line takes roughly 27 seconds to convert. The identical payload with one
xcharacter prefixed — which fails the parser's own leading-character guard — takes 0.011 seconds.preg_last_error()returns0at every input size tested, including runs of 160,000 characters, so PCRE never reachespcre.backtrack_limitand this is sustained CPU consumption rather than an early bail-out.2. Reference link label lookup — effectively quadratic, affected from 0.6.0.
When a shortcut or collapsed reference link is attempted,
CloseBracketParser::tryParseReference()copies the entire span between the brackets and passes it toReferenceMap::get(), which normalizes the label — up to four full passes over its length (trim,preg_replace,mb_check_encoding, andstrtolower, ormb_convert_caseon the non-ASCII path). Nested brackets produce one such lookup per closing bracket, each on a span two characters longer than the last.In 2.x the normalization sits behind an early return for an empty reference map, so a single 8-byte reference definition anywhere in the document (
[x]: y) is enough to unlock the path. At n = 64,000 nested brackets the same input takes 22.0 seconds with that line present versus 0.59 seconds without it. A single non-ASCII character inside the brackets forces themb_convert_casebranch, costing roughly 2.5x more again.3. Emphasis, strikethrough, and highlight delimiter processing — super-linear, affected from 2.6.0.
DelimiterStack::processDelimiters()remains linear only because of theopenersBottommemo, which bounds the backward opener scan — an argument that holds only if the memo's key space is O(1).EmphasisDelimiterProcessor::getCacheKey(), and the equivalents inStrikethroughDelimiterProcessorandMarkDelimiterProcessor, embed the closer's raw current run length in the key, leaving that space unbounded. An attacker spends O(n) bytes minting a growing number of distinct run lengths; each distinct length is a fresh key whose recorded bound starts at zero, forcing a full backward re-scan of the entire pile of openers.The resulting work grows as roughly n^1.5. This is sub-quadratic, but the amplification over linear growth itself scales with input size, so it worsens as inputs grow: 800 KB of ordinary asterisks, letters, and spaces costs roughly 27 seconds on a stock converter.
This path is a regression introduced in 2.6.0. Before that release the cache key was the bare delimiter character — a bounded key space that amortized correctly.
*and_are affected on any default configuration from 2.6.0 onward.~(StrikethroughExtension, included inGithubFlavoredMarkdownConverterandGithubFlavoredMarkdownExtension) is affected from 2.6.0.=(HighlightExtension) is affected only from 2.9.0, whenMarkDelimiterProcessorwas declared cacheable.Overall impact. An unauthenticated attacker who can submit Markdown for conversion can use a comparatively small request to consume disproportionate CPU time. Repeated or concurrent requests can occupy all available PHP workers and prevent legitimate requests from completing. The impact is limited to availability: no data is disclosed, rendered output is unchanged, and no rendering restriction is bypassed. Applications that process only trusted Markdown are not remotely exploitable.
Settings such as
html_input,allow_unsafe_links, andmax_nesting_leveldo not mitigate any of these, because the expensive work occurs during parsing, before rendering.max_delimiters_per_linebounds the third path only, and does so lossily — it silently discards emphasis once the cap is exhausted.Patches
The issues are patched in
2.9.1and later:[afollowed by 998 spaces andb]against a[a b]: /urldefinition — previously rendered as a link and now renders literally. This follows cmark, which applies its own label-length cap before normalizing (cmark_reference_lookup()), and matches how this library has always handled the equivalent[text][label]form viaLinkParserHelper::parseLinkLabel(). commonmark.js normalizes first and still resolves such labels.min(length, 2)for emphasis,min(length, 3)for strikethrough and highlight — restoring a bounded key space while preserving byte-identical output.Versions from
0.6.0through2.9.0are affected by at least one of these paths; see the table above for which paths apply to which releases. The 0.x and 1.x release lines are no longer supported, so their users must upgrade to2.9.1or later.Workarounds
If you cannot upgrade immediately, enforce a maximum length for individual lines before passing input to the converter, in addition to a total request-size limit. A per-line limit matters because every trigger described above fits within a single line. Because the cost grows super-linearly, the cap must be genuinely small to bound worst-case CPU.
Setting
max_delimiters_per_linereduces exposure to the delimiter path only, and does so by silently dropping emphasis from the rendered output. It has no effect on the fenced code or reference link paths.Restricting conversion to trusted users, applying strict execution-time limits, rate-limiting requests, and limiting concurrent conversions all reduce exposure, but none is a complete substitute for upgrading.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
thephpleague/commonmark (league/commonmark)
v2.10.0Compare Source
This is a security release to address a denial of service vulnerability in the
AttributesExtension.Added
table_of_contents/max_placeholder_entriesoption to limit how many table of contents entries a document may render across all of its placeholders (#1134)Cursor::matchInPlace(), which matches a regular expression at the cursor's position within the line using PCRE's native offset semantics instead of copying the remainder (#1145)\Ganchors at the cursor,^anchors at the start of the line, and lookbehinds and\bsee the characters actually preceding the cursor; this keeps scanning loops linear and enables left-context assertions thatmatch()cannot expressRegexHelper::PARTIAL_LINK_TITLE_UNANCHOREDandRegexHelper::PARTIAL_LINK_DESTINATION_BRACES, unanchored fragments so each call site can supply its own anchordefault_attributesconfiguration format which pairs the node attribute map with a newstrict_callablesoption:['default_attributes' => ['attributes' => [...], 'strict_callables' => true]]. Withstrict_callablesenabled, only closures and invokable objects are treated as callbacks, so strings and arrays are always used as literal attribute values. Callbacks written as string or array callables can be wrapped withClosure::fromCallable(). The original format - passing the node map directly - is still accepted, and defaultsstrict_callablestofalse.slug_normalizer/reservedoption which treats the given slugs as already-used, so colliding headings receive an incremental numeric suffix just like duplicate headings do (#1080)Changed
TableOfContentsextension to render the table of contents once and share it across all placeholders instead of cloning it into each one (#1134)TableOfContentsnode is no longer called once per placeholder, so it must return the same markup each time it is called for a given document (#1134)TableOfContentsnode for listeners which locate and reposition it (#1143)$environment->getConfiguration()->get('default_attributes')now returns the normalized structure withattributesandstrict_callableskeys instead of the node map; readdefault_attributes/attributesto get the map. Configuration written in either format continues to work unchanged.Deprecated
RegexHelper::PARTIAL_LINK_TITLEandRegexHelper::REGEX_LINK_DESTINATION_BRACES; use the unanchored variants with an explicit anchor insteaddefault_attributesstrict_callablesoption, which will be removed in 3.0 when only closures and invokable objects will ever be treated as callbacks.Fixed
default_attributesvalues which happen to match the name of a PHP function - such as'class' => 'link','header','key','range', or'current'- being invoked as callbacks, producing errors likelink() expects exactly 2 arguments, 1 given. Enablestrict_callablesto treat strings and arrays as literal attribute values (#1123)DefaultAttributesExtensionre-testing every configured value withis_callable()once per matching node, which asked the autoloader whether the first element of each array value named a real class every single timedefault_attributesvalue which PHP treats as callable reporting its failure from inside whichever function it collided with; the error now names the attribute and node class responsible, and keeps the original error as its previous exceptionUniqueSlugNormalizerInterfaceimplementations being wrapped by the built-inUniqueSlugNormalizerand never receiving the documentedclearHistory()calls, which caused slug history to leak across documents whenslug_normalizer/uniquewas set to'document'(#1080)AttributesExtensionre-merging and re-filtering everything a node had already collected each time another attribute node was applied to it, causing long runs of distinctly-named attributes to be resolved in quadratic time, which could be abused to cause a denial of service - this completes the fix for GHSA-jjv6-8j6v-6j52, which covered only theclassattribute (GHSA-8rr7-cvq3-gmfh)AttributesExtensionre-merging everything an attribute block had already collected on each of its continuation lines, causing long runs of distinctly-named attributes on consecutive lines to be resolved in quadratic time, which could be abused to cause a denial of service (GHSA-8rr7-cvq3-gmfh)v2.9.2Compare Source
This release fixes a regression introduced in 2.9.0 which changed the behavior of
Cursor::match()for certain regular expression patterns.Changed
Cursor::advanceToNextNonSpaceOrNewline()to scan the line in place instead of copying everything left in the block on every callFixed
Cursor::match()treated text before the cursor as part of the match subject (#1145). Patterns were matched against the whole line at an offset, which silently changed the meaning of\b,\B,\A, lookbehinds, a^anywhere other than the very start of the pattern, and a leading^combined with themmodifier.match()once again matches against the remainder, exactly as it did in 2.8; the core parsers keep the optimized in-place matching via a new internal method with PCRE's native offset semantics, anchoring their patterns at the cursor with\Garia-hidden="true"remaining in the keyboard tab order; they are now also giventabindex="-1", as a focusable element removed from the accessibility tree has no accessible name to announce when focused (WCAG 4.1.2)datawith the node they were cloned from, so that setting an attribute on either one also set it on the otherv2.9.1Compare Source
This is a security release to address multiple denial of service vulnerabilities and one cross-site scripting (XSS) vulnerability.
Changed
[label]and[label][]) now apply the spec's 999-character link label limit when resolving the label, matching the limit already enforced when parsing reference definitions and when resolving the[text][label]form. A label longer than 999 characters which collapsed to a shorter, defined label once whitespace was normalized will no longer resolve; this matches cmark's behavior.Fixed
{<FF>onclick="..."}) bypassing both theon*event handler filter and theallow_unsafe_linksprotection, as browsers treat that byte as whitespace and parse the name as a genuineonclickorhref(GHSA-f8fg-pg57-v4j8)SmartPunctExtensionrecopying the whole preceding text node when replacing each unpaired quote, causing documents with many apostrophes to be processed in quadratic time, which could be abused to cause a denial of service (GHSA-jjv6-8j6v-6j52)AttributesExtensionscanning the remaining siblings of every block-level attribute node, causing long runs of adjacent attribute blocks to be resolved in quadratic time, which could be abused to cause a denial of service - this completes the fix for GHSA-g2gp-3wwq-f4ph, which covered only inline attributes (GHSA-jjv6-8j6v-6j52)AttributesExtensionrebuilding the accumulated class list on every merge, causing long runs of.classattributes to be resolved in quadratic time, which could be abused to cause a denial of service (GHSA-jjv6-8j6v-6j52)Configuration
📅 Schedule: (in timezone UTC)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.