Repository navigation
Security patches (stable/2.1.x) - #444
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
renovate
Bot
force-pushed
the
renovate/stable/2.1.x-security-patches
branch
2 times, most recently
from
November 9, 2026 23:02
1f79fa7 to
89bbb3d
Compare
renovate
Bot
force-pushed
the
renovate/stable/2.1.x-security-patches
branch
from
November 13, 2026 18:56
89bbb3d to
ec397b7
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.
Note
This PR body was truncated due to platform limits.
This PR contains the following updates:
4.1.8→4.1.96.16.0→6.16.11.53.1→1.53.31.53.1→1.53.34.4.3→4.6.6Incorrect handling of embedded SVG and MathML leads to mutation XSS
GHSA-934p-vp7m-gx3c / RUSTSEC-2026-0533
More information
Details
The MathML text integration points (
mi,mo,mn,ms,mtext) and SVGforeignObjectcan be made to contain a tag in the other one's namespace (a MathML integration point with a child in the SVG namespace, or vice versa) without the root tag that switches out of the HTML namespace. If the attacker can construct input that parses differently in as HTML than as foreign XML, they can inject arbitrary JavaScript code into the user's browser.For example:
<math><mi><svg><gadget></svg></mi></math>.math,mi, and the gadget, but notsvg.<math><mi><gadget></mi></math>.As far as we know, the gadget can only be written using a tag that is parsed as raw text in HTML. These elements are:
Applications that do not explicitly allow any of these tags should not be affected, since none are allowed by default.
This vulnerability was reported by Roger Meyer.
Severity
Unknown
References
This data is provided by OSV and the Rust Advisory Database (CC0 1.0).
qs : qs.stringify with arrayFormat 'comma' throws an uncaught TypeError on array elements carrying a non-callable own toString (DoS)
CVE-2026-110816 / GHSA-6pq8-jhm2-2vcw
More information
Details
Summary
qs.stringify(obj, { arrayFormat: 'comma' })throws an uncaughtTypeError: Cannot convert object to primitive valuewhen an array inobjcontains an element that carries an own, non-callabletoStringproperty (for example{ a: [ { toString: 'x' } ] }). A remote, unauthenticated attacker who can influence an object that the application later re-serializes with the comma array format triggers the throw. In a service that lacks a synchronous error boundary around the serialization call, the uncaught exception crashes the worker process, producing a denial of service.Root Cause
When
arrayFormat: 'comma'is selected, the comma branch collapses the whole array into a single value viaArray.prototype.join, or, underencodeValuesOnly: true, maps each element through the value encoder before joining. Both paths perform an implicit string coercion (ToPrimitivewith hint"string") on each element. For an object whose owntoStringis a non-callable value, coercion skips the shadowed non-callabletoString, falls through toObject.prototype.valueOf(which returns the object rather than a primitive), and throws. The comma branch runs this coercion before the per-element null and skip handling in the main loop, so nothing downstream can neutralize the hostile element, and the throw is never caught inside the library.Impact
Prerequisites: the application calls
qs.stringifywitharrayFormat: 'comma'(a documented, supported option) on an object whose shape can be influenced by attacker input. Attacker-controllable sources includeqs.parse(input, { allowPrototypes: true }), which retains atoStringsegment (Express 4's default query parser, Express 5'sextendedquery parser, and body-parser'sextendedurlencoded parser all set it),qs.parse(input, { plainObjects: true }), whose null-prototype elements throw even without atoStringkey (eg,a[][b]=c), andJSON.parseof a request body, which needs no qs parse option at all. No authentication or user interaction is required. Demonstrated capability: a single request forces an uncaught synchronousTypeErrorin the serialization call. In a naive single-process Node service with no synchronous error boundary, this crashes the process and takes the service offline (availability impact). Under a framework such as Express that traps synchronous handler throws, the plausible outcome is a per-request 500 rather than a full outage; that lower-impact case is noted but not the worst credible supported deployment. There is no confidentiality or integrity impact, no memory unsafety, and no prototype pollution.Proof of Concept
Install qs at the affected version (for example 6.16.0) and run the following script with Node.js. No network setup is required; it demonstrates the throw in isolation.Attack Chain
qs.stringify(obj, { arrayFormat: 'comma' }).{ a: [ { toString: <non-callable value> } ] }, either viaa[0][toString]=xparsed withallowPrototypes, or via a JSON body{"a":[{"toString":"x"}]}.stringify, the primitive/buffer guard atlib/stringify.js:134is false for an array, so control reaches the comma branch atlib/stringify.js:149.encodeValuesOnlypath, the closurev == null ? v : encoder(v)atlib/stringify.js:152-154passes onlynull/undefinedthrough; a non-null object still reaches the encoder. The default path skips that closure entirely and reachesobj.join(',')atlib/stringify.js:156with no guard at all.Array.prototype.join, orString(str)atlib/utils.js:292).ToPrimitiveskips the non-callable owntoString,valueOfreturns the object, and aTypeErroris thrown.Bypass Evidence
This is a different element type on the code path CVE-2026-8723 (GHSA-q8mj-m7cp-5q26) patched, plus the default comma path, which that fix never covered. CVE-2026-8723 addressed a
TypeErrorcrash onnull/undefinedentries in the comma plusencodeValuesOnlypath. Its fix (commit 21f80b3) wraps the encoder infunction (v) { return v == null ? v : encoder(v); }, so it only passesnullandundefinedthrough. A non-null element with a hostile owntoStringfails thev == nulltest, so the encoder still runs and still throws; the encodeValuesOnly case (case C above) throws on the exact fixed code. The default comma path (encodeValuesOnlyunset, the library default) never entered that fix at all:git log -S "obj.join(','" -- lib/stringify.jsshows no security fix has ever touched theobj.join(',')line, and cases A and B throw withencodeValuesOnlyunset. The related isBuffer hardening for CVE-2026-82417 (commit e83d321) is a different sink at thelib/stringify.js:134guard, which is never entered for the array element; the negative control{a:{constructor:{isBuffer:'x'}}}serializes cleanly. Disproof attempts that failed: avalueOf-only object does not throw (it serializes to[object Object]), confirming the trigger is an element with no callabletoString(an own non-callabletoString, or a null-prototype object with notoStringat all, asqs.parseproduces underplainObjects); nested arrays ({"a":[[{"toString":"x"}]]}) throw the same way; a callabletoStringserializes cleanly; and the default (non-comma) array format serializes cleanly, confirming the comma format is required. All positive and negative cases were reproduced on the exact published 6.16.0 artifact.Affected Versions
Ecosystem: npmPackage: qsConfirmed affected range: >= 6.7.0, <= 6.16.0Latest release checked: 6.16.0 (npm latest; git tag v6.16.0)Fix status: fixed in 6.16.1 (a952e75)The
arrayFormat: 'comma'join sink was introduced in qs 6.7.0, so 6.7.0 is the lower boundary; releases before 6.7.0 lack the sink. No released version fixes this vector, and the latest published release (6.16.0) reproduces the throw, so the closed upper bound<= 6.16.0covers every affected release. TheencodeValuesOnlysub-path was added later, but the default comma-join vector already affects 6.7.0, so 6.7.0 governs the lower boundary.Suggested Fix
The comma array serialization must not allow an implicit string coercion of an array element to throw an uncaught exception. Coercion of each comma element should be performed defensively (for example by wrapping the join and per-element encode so that a coercion failure is caught and handled), and this protection must cover both the default
obj.join(',')path and theencodeValuesOnlyencoder path, not only the previously patchednull/undefinedcase. As an interim mitigation without a code change, applications can avoidarrayFormat: 'comma'when serializing data derived from untrusted input, sanitize parsed objects (avoidallowPrototypes/plainObjectson untrusted input and strip unexpected own properties), or wrapqs.stringifycalls in a synchronous error boundary so a coercion failure cannot crash the process.Reported by zx (GitHub: @manus-pi).
Independent report by @Lucidsec
The following was reported separately, after this advisory, and is merged here as a duplicate.
Summary
In project qs, in versions
>= 6.7.0, <= 6.16.0(every version that supportsarrayFormat: 'comma'),qs.stringifywitharrayFormat: 'comma'can throw an uncaughtTypeError: Cannot convert object to primitive valuewhen an array element has a non-callable owntoString. It is fixed in 6.16.1. Related: CWE-248 and CWE-704.Technical Details
qs.stringifywitharrayFormat: 'comma'joins an array atlib/stringify.js:156viaobj.join(','). An element whose owntoStringis not callable makesArray.prototype.jointhrow. There is no type check and no catch on that path.A second path exists with
encodeValuesOnly: atlib/stringify.js:151-154,maybeMaponly skipsv == null, thenlib/utils.js:292doesString(str)and throws the sameTypeError(this second site exists since v6.11.1; before that, the same input throws atjoin).Who can trigger: someone who can shape an array element passed to
stringify. The host must use non-defaultarrayFormat: 'comma'. DefaultarrayFormatindicesdoes not fold arrays and is not affected. A parse-then-stringify path also needsplainObjects: true(null-prototype elements fromlib/parse.js:200) orallowPrototypes: true(which Express 4's default query parser, Express 5'sextendedquery parser, and body-parser'sextendedurlencoded parser all set). Defaultqs.parse('a[0][toString]=x')returns{}because the prototype guard dropstoString. Direct JSON handed tostringifycan supply{"a":[{"toString":"x"}]}.Cause: the comma fold at
lib/stringify.js:149-156collapses the array into a single value before the main loop atlib/stringify.js:172-212, soskipNullsandstrictNullHandlingonly ever see the joined value, never individual elements.isNonNullishPrimitive/isBufferatlib/stringify.js:134inspect the whole value, not each element. A normal object usesObject.prototype.toStringand becomes[object Object]. An own non-callabletoStringis skipped,valueOfreturns the object, andjointhrows. (The skipped TODO test attest/stringify.js:684-689uses a plain{ b: 1 }element, which does not throw; it covers the separate question of what comma format should output for object elements, not this crash.) Earlier comma crash fixes did not cover object elements.Impact
One small input makes that serialization path throw a synchronous, catchable
TypeError. Behind a framework error boundary (eg, a synchronous Express handler), the request fails with a 500 and the process survives. In a host with no error boundary (eg, a barehttp.createServerhandler), the uncaught exception exits the process (the client seesECONNRESET). Availability only.Proof of Concept
Show the proof of concept
Checked on the latest commit that was checked:
07b1d4d82c8f9301c105ea4b94fa2302cfd6e8b4. Still present. Demonstrated.{"a":[{"toString":"x"}]}throws atlib/stringify.js:156.{"a":["x","y"]}returns 200 with bodya=x%2Cy.a=%5Bobject%20Object%5Dand does not throw.encodeValuesOnly: truethrows viautils.js:292.plainObjectsparse plus comma throws.Suggested Fix
Before
join, map elements with the existing primitive check; skip or replace non-primitives sojoincannot throw. On theencodeValuesOnlypath, do not send non-primitives intoString(). Optionally guardlib/utils.js:292. Add new regression tests.Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
AsyncFd::newand related constructors violate I/O safetyRUSTSEC-2026-0386
More information
Details
tokio::io::unix::AsyncFdprovides safe constructors (new,with_interest,try_new, andtry_with_interest) that accept anyT: AsRawFdrather than requiring proof of ownership or validity of the file descriptor. BecauseRawFdimplementsAsRawFd, safe code can construct anAsyncFdfrom an arbitrary or closed file descriptor, or close/replace the underlying file descriptor while theAsyncFdis still alive.This violates I/O safety in two ways:
AsyncFd<T>implementsAsFdfor allT: AsRawFdby callingBorrowedFd::borrow_raw(self.as_raw_fd()), allowing safe code to obtain an arbitraryBorrowedFd<'_>without owning the file descriptor.epoll/kqueueuser data for registered file descriptors. If the underlying file descriptor is duplicated and then closed while anAsyncFdis alive, and the OS reuses that file descriptor number for a another IO resource on the same runtime, dropping the firstAsyncFdderegisters the reused file descriptor number and frees the first while the original file description remains registered inepoll, leading to a use-after-free when a readiness event fires.Starting in Tokio 1.51.6, 1.53.3, and 1.54.0,
AsyncFd::new,AsyncFd::with_interest,AsyncFd::try_new, andAsyncFd::try_with_interestare deprecated in favor of theunsafeconstructorsAsyncFd::registerandAsyncFd::register_with_interest. Callers must ensure that the file descriptor remains valid, open, and unchanged for the lifetime of theAsyncFd.Severity
Unknown
References
This data is provided by OSV and the Rust Advisory Database (CC0 1.0).
Zod can exhaust memory while validating oversized constrained collections
CVE-2023-54404 / GHSA-mrhx-c7xc-m3w5
More information
Details
Zod schema-validation library through 4.6.5 contains an uncontrolled resource consumption vulnerability that allows attackers to exhaust memory by submitting a large array to an application using an array schema without a length constraint. Attackers can exploit the handleArrayResult parse logic in $ZodArray, which accumulates every validation issue for each failing element with no cap or early termination, causing the process to allocate excessive issue objects and crash due to out-of-memory conditions.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
rust-ammonia/ammonia (ammonia)
v4.1.9: 4.1.9Compare Source
ljharb/qs (qs)
v6.16.1Compare Source
parse: do not mutate an object inputstringify: stop re-encoding structural separator dots whenencodeDotInKeysis set (#564)stringify:arrayFormat: 'comma': pass the full encoder arguments withencodeValuesOnlyutils: encode+as%2Bin iso-8859-1 mode so values round-trip (#565)stringify: ignore inherited array format names (#622)stringify:arrayFormat: 'comma': do not throw on elements with no callabletoStringutils:merge: seed an overflow container's index from its own keys, not just the sourceutils:merge: keep astrictMergeconflict container's index andarrayLimitcorrectparse: only treat[]as array syntax when it ends the keydecode: skip decoders when there is no percent sign (#583)utils:merge: applyarrayLimitto the two-element array built for colliding valuesparse: bound the nesting added by repeatedstrictMergeconflicts (credit @Yeaseen)qsand flat parsers disagree about parameter namesthrowOnLimitExceededlimits each array, not the total number of valuescache-modeutils:decode: add missing casesparse: characterize the]=split when an=precedes any bracket group (#620)parse:allowDots: cover stray close brackets before a dot@ljharb/eslint-config,eslint,tapetokio-rs/tokio (tokio)
v1.53.3: Tokio v1.53.3Compare Source
1.53.3 (October 13th, 2026)
Added
AsyncFd::registerandAsyncFd::register_with_interest(#8587)Changed
AsyncFd::{new, with_interest, try_new, try_with_interest}(#8587)Fixed
DuplexStreamwakers outside the lock (#8618)unreachable_codeinjoin!andtry_join!forInfallible(#8518)current_thread(#8595)Fixed (unstable)
io_uringop alive when submission fails after push (#8185)v1.53.2: Tokio v1.53.2Compare Source
1.53.2 (October 3rd, 2026)
Fixed
AsyncFdregistration list on deregister" (#8540)Permitbefore sending value (#8560)MAX_PERMITSinSemaphore::acquire(#8548)Sender::closedoutside mutex (#8558)JoinSet(#8554)clear_entry(#8552)Fixed (unstable)
io_uringread length tou32::MAX(#8572)current_threadtask dumps from other runtimes (#8544)io_uringcontext if a completion waker panics (#8566)colinhacks/zod (zod)
v4.6.6Compare Source
Commits:
0cd3af5docs: load the en locale directly in Zod Mini9d5e60fdocs: import locales from zod/locales, not z.locales34a626fdocs: tighten the z.locales tree-shaking note74304cerelease: stage npm versions instead of publishing them (#6622)b2ef983docs: add Code for Japan to bronze sponsors8fb2fafdocs: crop the Code for Japan logo and list it first in bronzebacad51docs: square the Code for Japan logo to match the other bronze tilesc42596brelease: hold the run on the release-approval environment until the staged versions are approved (#6638)a2ba4a6fix(types): declare record output and input as members, not base type arguments (#6645)a0ebf97fix(v4): check array, set and map size bounds before parsing elements (#6652)529f78d4.6.69c21983ci: stage at verbose so a failed OIDC token exchange says whyv4.6.5Compare Source
Commits:
d2b135cdocs: add the 4.6.x patch highlights to the 4.6 postf1448f7docs: fold the 4.6.x patch highlights into the 4.6 post's own sectionsde65a5cdocs: lead the properties section with the check and add a Zod Mini tab (#6598)56222cdfeat(instanceof): key the .properties() shape off the instance type (#6600)ca0229aRevert "feat: add z.currencyCode() over a vendored ISO 4217 list, refreshed weekly by CI (#6595)"cc4cd4eRevert "Revert "feat: add z.currencyCode() over a vendored ISO 4217 list, refreshed weekly by CI (#6595)""0f3f5ee4.6.559bbc03chore: re-pin the integration peers to the workspace zod after the 4.6.5 bumpv4.6.4Compare Source
A patch on top of 4.6.3.
d6bc1e30feat: addz.currencyCode()over a vendored ISO 4217 list, refreshed weekly by CI (#6595)ad32d751perf:z.url()rejects an invalid URL withURL.canParse()instead of a throwing constructor, about 50x faster; fewer allocations on the validation path (#6588)2bb08717chore: re-pin the integration peers to the workspace zod after the 4.6.4 bumpf6e1701achore(deps): bump next to 15.5.25 and vite to 7.3.6 (#6153)v4.6.3Compare Source
A patch on top of 4.6.2.
413cce9afix(v4): make z.properties() a check again (#6594) — removes the standalonez.properties()schema from 4.6.0;z.instanceof().properties()and.check(...z.properties())are unchanged75d63ee1docs: show only the.properties()method form in the 4.6 post46da9572docs: match the error-message examples to what the parsers emitv4.6.2Compare Source
A patch on top of 4.6.1.
9446b5ccfix: preserve undefined prefault outputs and object keys (#6587) — closes #65850c483c58docs: the Zod 4.6 announcement post (#6546)a00c3f34docs: use Trigger.dev's brand-kit lockups for the platinum cardv4.6.1Compare Source
A patch on top of 4.6.0.
b12aa523fix: preserve unique tags with defaulted discriminators (#6582) — closes #6577dd9c36fafix(v4): defer recursive object index inference (#6580)3b154992feat(lang): add Tajik (tg) locale (#6581) by @ismoil772efa8b80ci: give the npm wait a real budget and drop the back-publish path (#6583)v4.6.0Compare Source
Zod 4.6 is now available.
At a glance:
.validate()— checks input validity without building a result (up to 35x faster than.safeParse().successon a compiled schema)z.instanceof().properties()— validates properties of an instancefromJSONSchema()— enforces six validation keywords it used to ignorez.iban()— electronic-format IBAN plus mod-97 checksumz.withParser()— installs a parser generated elsewhere, for environments withoutnew Functionz.validate()underrequire)@zod/mini— Zod Mini as a standalone package, versioned in lockstep withzodsince 4.5.validate()Standalone boolean validation, in Zod, Zod Mini, and Zod Core. It answers "is this input valid?" without constructing a
ZodError, which makes rejection cheap. The return type is a guard on the schema's input type.It is a method on Zod Classic schemas too. (#6547)
In conjunction with
z.compile(), this can be up to 35x faster than.safeParse().successon invalid input.Time per call on invalid input, compiled with z.compile() — lower is better (benchmark)
Uncompiled schemas
Without compilation it is up to 5.9x faster. The saving is the result object:
.safeParse()allocates one with an accessor pair on every call, and.validate()allocates nothing.Time per call on invalid input, plain schemas — lower is better (benchmark)
Both charts measure the failure path. The key feature of
.validate()is that it can short-circuit on the first issue it encounters, instead of aggregating a fullZodIssue[]array.z.properties()A new API for validating specific properties of an object. Unlike
z.object()it validates in-place, so it plays nice with class instances. (#6536)A corresponding
.properties()method has been added toZodInstanceOf.Zod
Zod Mini
The input comes back untouched, so the prototype survives and the methods still work. That is the part
z.object()cannot do: it would hand back a plain object and theResponsewould be gone.fromJSONSchema()Six additional JSON Schema keywords are now supported in
z.fromJSONSchema(). (#6535)minProperties/maxPropertiesuniqueItemscontainsminContains/maxContainsBoth property bounds count the input's own keys. Array uniqueness is structural, so
[{ a: 1 }, { a: 1 }]is a duplicate.z.iban()A new string format: an IBAN in electronic format, with a valid ISO 7064 MOD 97-10 checksum. (#6571)
z.withParser()z.compile()builds its parser withnew Function, which a strict Content Security Policy blocks.z.withParser()is that installer on its own: it takes a parser generated somewhere else, at build time or by a native compiler, and installs it under the same contract. (#6575)The supplied parser owns the whole result, so it has to return what the schema would have returned. This one rebuilds the object rather than handing back its input, because
z.object()strips unknown keys. Returningz.INVALIDhands the input to the runtime, which stays the only source ofZodErrors.Faster CommonJS
TypeScript compiles a re-export to a getter, and 252 of the 255 exports on Zod 4.5's CommonJS entrypoint were getters. V8 could not see a constant callee behind one, so it could not inline the call. The 4.6 build emits plain properties and freezes the exports object. On a compiled schema,
z.validate()underrequireis about 3x faster than it was in Zod 4.5. (#6564)Only calls through the namespace were affected. A method call like
Player.safeParse(data)never reads the exports object, and the ESM build is unchanged.Memory retention in recursive schemas
A recursive schema held the input and output of its last parse until the next parse replaced it, so one long-lived schema pinned every object it had touched. Zod 4.4 released that input and Zod 4.5 did not, which surfaced as an out-of-memory failure on a repository-wide lint run. The parse state is weak throughout now: one parse of a 29k-node tree retains 2.2 MB where it used to retain 10.1 MB, and recursive parses give up about 6% for it. (#6572)
Bug fixes
errorBecause
safeParse()now builds its error lazily, error maps — global, locale, and per-schemaerror— run whenresult.erroris first read, not at parse time. Code that swapsz.config()between the parse and the read gets the newer configuration. (#6519)An error map with a side effect never
Configuration
📅 Schedule: (in timezone Europe/Warsaw)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.
This PR was generated by Mend Renovate. View the repository job log.