fix(deps): Playwright 1.64.1 (Chromium 156) for CVE-2026-106378 (#3907)

Playwright 1.62.1 bundled Chromium 151.0.7922.34, which lacks the macOS GPU-process TCC fix (Chromium 0c2f3e54b265, crbug.com/507596239). 1.64.1 bundles 156.0.8078.4, which has it. The playwright-core patch is regenerated from our 1.62.1 patch: the launch windowsHide and TcpPortRandomizationWin hunks carry over unchanged; the taskkill hunk is dropped because 1.64 passes windowsHide there upstream.

Co-authored-by: merit-blake <265362871+merit-blake@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
committed 2026-11-03 14:45:14 +00:00
1 parent 9a81eed59b
commit 75c3e0e925
10 files changed
+22 -34

No files matched your search

+1 -1
View File
@@ -1380,7 +1380,7 @@ browser's trust store and updates.
eight eMudhra intermediate CAs by CRLSet on 2026-10-17, the day their key
compromise was reported, and scheduled the removal of their root, emSign ECC
Root CA - G3, from the Chrome Root Store for 2026-10-27. The root store built
into gstack's pinned Playwright 1.62.1 (Chromium 151) still trusts that root, so
into gstack's pinned Playwright 1.64.1 (Chromium 156) still trusts that root, so
the headless browser accepts certificates those intermediates issued. That lasts
until gstack moves to the first Playwright release whose Chromium is
158.0.8115.0 or later, the first Chrome for Testing build measured to refuse
@@ -66,7 +66,7 @@ const nodeInfo = JSON.parse(nodeProbe.stdout);
if (nodeInfo.architecture !== process.arch || !['x64', 'arm64'].includes(process.arch)) incomplete('runtime_architecture_mismatch');
const require = createRequire(import.meta.url);
const playwrightVersion = require('playwright/package.json').version;
if (playwrightVersion !== '1.62.1') incomplete('playwright_1_62_1_required');
if (playwrightVersion !== '1.64.1') incomplete('playwright_1_64_1_required');
const versionProbe = spawnSync(path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'), [
'-NoProfile', '-NonInteractive', '-Command', NATIVE_BROWSER_VERSION_COMMAND,
], { env: { ...environment, GSTACK_QUALIFY_BROWSER_EXE: executable }, encoding: 'utf8', timeout: 10_000, windowsHide: true });
+1 -1
View File
@@ -213,7 +213,7 @@ async function qualifiedAdapterFixture() {
const receipt = {
browserName: 'Edge', architecture: runtime.architecture, windowsRelease: release(),
executableSha256: '0'.repeat(64), nodeVersion: runtime.version, bunVersion: Bun.version,
playwrightVersion: '1.62.1', sourceHashes,
playwrightVersion: '1.64.1', sourceHashes,
};
const virtualRoot = `C:\\gstack-${path.basename(fixture)}`;
const windowsEnv = { LOCALAPPDATA: `${virtualRoot}\\Local`, PROGRAMFILES: `${virtualRoot}\\Apps`, 'PROGRAMFILES(X86)': `${virtualRoot}\\Apps32` };
+7 -7
View File
@@ -1,8 +1,10 @@
/**
* #2160/#1989: playwright-core is bun-patched to pass windowsHide at its two
* #2160/#1989: playwright-core must pass windowsHide at its two
* Windows-visible child_process sites — the browser launch spawn (Node
* defaults windowsHide to FALSE for spawn, so browser children could flash a
* console window) and the force-kill taskkill spawnSync. This is the repo's
* console window) and the force-kill taskkill spawnSync. The launch site is
* bun-patched; the taskkill site is upstream since Playwright 1.64 (#3907),
* so only the installed-tree check below covers it. This is the repo's
* first patchedDependencies entry; these static checks pin the three-legged
* coherence (patch file ↔ package.json ↔ installed tree) so a playwright
* bump that forgets to re-target the patch fails CI instead of silently
@@ -35,15 +37,13 @@ describe('playwright-core windowsHide patch (#2160, #1989)', () => {
expect(pkg.patchedDependencies[key]).toBe(`patches/playwright-core@${version}.patch`);
});
test('the patch file exists and carries both windowsHide sites', () => {
test('the patch file exists and carries the launch windowsHide site', () => {
const version = installedPlaywrightCoreVersion();
const patchPath = path.join(ROOT, 'patches', `playwright-core@${version}.patch`);
expect(fs.existsSync(patchPath)).toBe(true);
const patch = fs.readFileSync(patchPath, 'utf-8');
// Launch spawnOptions site.
expect(patch).toContain('+ windowsHide: true,');
// taskkill force-kill site.
expect(patch).toContain('shell: true, windowsHide: true');
});
test('bun.lock is coherent: the lockfile records the patched dependency', () => {
@@ -63,10 +63,10 @@ describe('playwright-core windowsHide patch (#2160, #1989)', () => {
// Windows Free Tests 40656299153 and 41056150287 (cookie-picker-ui, serial retry passed): goto failed with
// net::ERR_NO_BUFFER_SPACE on 127.0.0.1. Chromium's TcpPortRandomizationWin raises WSAENOBUFS with ports free;
// microsoft/playwright#43605 disables it in 1.65, and the 1.62.1 patch backports it; drop this block at 1.65.
// microsoft/playwright#43605 disables it in 1.65, and the 1.64.1 patch backports it; drop this block at 1.65.
describe('playwright-core TcpPortRandomizationWin backport (microsoft/playwright#43605)', () => {
test('the patch and the installed tree disable the feature in the --disable-features list', () => {
expect(fs.readFileSync(path.join(ROOT, 'patches', 'playwright-core@1.62.1.patch'), 'utf-8')).toContain('+ "TcpPortRandomizationWin"');
expect(fs.readFileSync(path.join(ROOT, 'patches', `playwright-core@${installedPlaywrightCoreVersion()}.patch`), 'utf-8')).toContain('+ "TcpPortRandomizationWin"');
const bundle = fs.readFileSync(path.join(ROOT, 'node_modules', 'playwright-core', 'lib', 'coreBundle.js'), 'utf-8');
const list = bundle.slice(bundle.indexOf('disabledFeatures = ['), bundle.indexOf('].filter(Boolean);', bundle.indexOf('disabledFeatures = [')));
expect(list).toContain('"TcpPortRandomizationWin"');
+1 -1
View File
@@ -251,7 +251,7 @@ describe('cookie-import domain validation', () => {
reset: 'not_requested', verification: { verified: false, reason: 'not_requested' }, message: 'Cookie copy complete.',
});
let currentUrl = 'https://example.test';
const page = { url: () => currentUrl, isClosed: () => false };
const page = { url: () => currentUrl, isClosed: () => false } as any;
const session = { getPage: () => page, getActiveFrameOrPage: () => page, getFrame: () => null } as any;
const manager = { trackCookieImportDomains() {} } as any;
try {
+4 -6
View File
@@ -13,7 +13,7 @@
"html-to-docx": "1.8.0",
"html-to-vdom": "0.7.0",
"marked": "^18.1.1",
"playwright": "^1.62.1",
"playwright": "^1.64.1",
"sharp": "^0.35.4",
"socks": "^2.8.10",
"xterm": "^5.3.0",
@@ -28,7 +28,7 @@
},
},
"patchedDependencies": {
"playwright-core@1.62.1": "patches/playwright-core@1.62.1.patch",
"playwright-core@1.64.1": "patches/playwright-core@1.64.1.patch",
},
"overrides": {
"@hono/node-server": "2.1.6",
@@ -335,8 +335,6 @@
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
@@ -469,9 +467,9 @@
"platform": ["platform@1.3.6", "", {}, "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="],
"playwright": ["playwright@1.62.1", "", { "dependencies": { "playwright-core": "1.62.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg=="],
"playwright": ["playwright@1.64.1", "", { "dependencies": { "playwright-core": "1.64.1" }, "bin": { "playwright": "cli.js" } }, "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA=="],
"playwright-core": ["playwright-core@1.62.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw=="],
"playwright-core": ["playwright-core@1.64.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ=="],
"prettier": ["prettier@3.9.10", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA=="],
+2 -2
View File
@@ -77,7 +77,7 @@
"html-to-docx": "1.8.0",
"html-to-vdom": "0.7.0",
"marked": "^18.1.1",
"playwright": "^1.62.1",
"playwright": "^1.64.1",
"sharp": "^0.35.4",
"socks": "^2.8.10",
"xterm": "^5.3.0",
@@ -115,6 +115,6 @@
"sharp": "0.35.5"
},
"patchedDependencies": {
"playwright-core@1.62.1": "patches/playwright-core@1.62.1.patch"
"playwright-core@1.64.1": "patches/playwright-core@1.64.1.patch"
}
}
@@ -1,8 +1,8 @@
diff --git a/lib/coreBundle.js b/lib/coreBundle.js
index d9041dd0f009072511a7d808dec83121ff29e127..542acd31dd7e8ae084de952dc42ec63d0caba849 100644
index 6893f1cf133efec2c5dccc35c77cc7a53870ccbc..7990e202c5b574ca5ea4c3e73c15c2da43a5b980 100644
--- a/lib/coreBundle.js
+++ b/lib/coreBundle.js
@@ -8906,6 +8906,10 @@ async function launchProcess(options) {
@@ -10031,6 +10031,10 @@ async function launchProcess(options) {
env: options.env,
cwd: options.cwd,
shell: options.shell,
@@ -13,16 +13,7 @@ index d9041dd0f009072511a7d808dec83121ff29e127..542acd31dd7e8ae084de952dc42ec63d
stdio
};
const spawnedProcess = childProcess.spawn(options.command, options.args || [], spawnOptions);
@@ -8985,7 +8989,7 @@ async function launchProcess(options) {
options.log(`[pid=${spawnedProcess.pid}] <will force kill>`);
try {
if (process.platform === "win32") {
- const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { shell: true });
+ const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { shell: true, windowsHide: true });
const [stdout2, stderr2] = [taskkillProcess.stdout.toString(), taskkillProcess.stderr.toString()];
if (stdout2)
options.log(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout2}`);
@@ -34634,7 +34638,10 @@ var init_chromiumSwitches = __esm({
@@ -36204,7 +36208,10 @@ var init_chromiumSwitches = __esm({
// Disables forced sign-in in Edge.
"msForceBrowserSignIn",
// Disables updating the preferred version in LaunchServices preferences on mac.
-1
View File
@@ -41,7 +41,6 @@
"browse/test/handoff.test.ts\tTS2554\tExpected 4 arguments, but got 3.": 2,
"browse/test/pair-agent-e2e.test.ts\tTS2532\tObject is possibly 'undefined'.": 1,
"browse/test/pty-inject-scan.test.ts\tTS2345\tArgument of type '{ Authorization?: undefined; } | { Authorization: string; }' is not assignable to parameter of type 'Record<string, string>'. Type '{ Authorization?: undefined; }' is not assignable to type 'Record<string, string>'. Property 'Authorization' is incompatible with index signature. Type 'undefined' is not assignable to type 'string'.": 1,
"browse/test/security-audit-r2.test.ts\tTS2769\tNo overload matches this call. The last overload gave the following error. Type '{ isClosed: () => boolean; url: () => string; }' is missing the following properties from type 'Page': evaluate, evaluateHandle, addInitScript, $, and 110 more.": 1,
"browse/test/server-auth.test.ts\tTS2345\tArgument of type '{ Host: string; Origin: string; } | { Host?: undefined; Origin: string; } | { Authorization: string; Host: string; Origin?: undefined; }' is not assignable to parameter of type 'Record<string, string>'. Type '{ Host?: undefined; Origin: string; }' is not assignable to type 'Record<string, string>'. Property 'Host' is incompatible with index signature. Type 'undefined' is not assignable to type 'string'.": 1,
"browse/test/server-factory.test.ts\tTS2769\tNo overload matches this call. The last overload gave the following error. Argument of type '\"local\"' is not assignable to parameter of type 'undefined'.": 1,
"browse/test/server-proxy-fail-fast.test.ts\tTS2339\tProperty 'subarray' does not exist on type 'string | NonSharedBuffer'. Property 'subarray' does not exist on type 'string'.": 1,
+2 -2
View File
@@ -48,8 +48,8 @@ describe('Ubuntu fallback retains CPU architecture', () => {
cwd: ROOT, env: { PATH: process.env.PATH, HOME: temp(), PLAYWRIGHT_HOST_PLATFORM_OVERRIDE: override }, encoding: 'utf8', timeout: 20_000,
});
expect(dryRun.status, dryRun.stderr).toBe(0);
expect(dryRun.stdout).toContain(expected === 'arm64' ? 'chromium-linux-arm64.zip' : 'chrome-linux64.zip');
expect(dryRun.stdout).not.toContain(expected === 'arm64' ? 'chrome-linux64.zip' : 'chromium-linux-arm64.zip');
expect(dryRun.stdout).toContain(expected === 'arm64' ? 'chrome-linux-arm64.zip' : 'chrome-linux64.zip');
expect(dryRun.stdout).not.toContain(expected === 'arm64' ? 'chrome-linux64.zip' : 'chrome-linux-arm64.zip');
}, 30_000);
}
for (const cpu of ['riscv64', 'i686', 'unknown']) test(`${cpu} reports unsupported instead of installing x64`, () => {