mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-03 18:06:54 +02:00
v1.90.0.0 feat: make browser cookie imports explicit and safe (#2964)
* fix(browse): prepare reliable cookie import wave for validation * ci: sequence quality and behavior for validation branch * fix(browse): isolate Windows qualification and preserve native diagnostics * test(browse): cover cookie workflow quality and isolate Windows user paths * test(browse): trace native member startup and initialize fresh folders * fix(browse): keep Windows member stdin alive through EOF * fix(browse): latch native timeouts and compare contained Edge startup * test(browse): verify native version metadata and actual Windows argv * test(browse): qualify Dia import on isolated macOS CI * fix(browse): require picker origin for session mutations * fix(browse): bound credential reads through stream completion * test(browse): inspect owned Windows process arguments natively * test(evals): preserve passing coverage during cookie repair reruns * test(browse): isolate Dia qualification in a fresh macOS account * test(browse): pass bounded integer timeouts to native Mac probes * test(browse): distinguish Windows profile initialization from containment * test(browse): await descendant pipe readiness before parent exit * test(browse): initialize and restore isolated macOS Keychain state * test(browse): initialize Windows fixture folders before qualification * test(ci): pin the same Node runtime across Windows checks * test(browse): distinguish native macOS browser preflight stages * test(browse): isolate Windows descendant console lifetime * test(browse): preserve native receipts and identify fixture lock holders * test(browse): prepare dependency resolution before native Mac worker startup * test(ci): include lock and close checks in native diagnostics * test(browse): preserve native owner probe stages and subprocess deadlines * fix(browse): classify Chromium profile-in-use exit precisely * test(browse): retain Mac qualification evidence through cleanup failures * test(browse): bound Mac fixture paths and retire its owned user domain * test(browse): accept vanished fixture entries without weakening cleanup * test(browse): identify probe-created macOS user domains safely * test(browse): observe Mac user domains without targeting them first * test(browse): use passive fresh-user ownership throughout Mac qualification * test(browse): distinguish profile and registered-home Keychain lookups * test(browse): qualify Dia under one registered account home * test(browse): identify Dia startup and owned process-group failures * test(browse): classify bounded Dia startup diagnostics without leaking output * fix(test): preserve native Mac sandboxing and reap owned browser children * fix(browse): preserve Chromium sandboxing for native profile imports * test(browse): inspect signed Mach-O architecture without launching Xcode tools * test(browse): sample pending Dia startup and reap on all cleanup paths * test(browse): compare protected Dia launches in fresh Bun and Node accounts * test(browse): inspect isolated Mac GUI readiness without browser access * v1.90.0.0 fix: bind cookie picker actions to their document * test: validate cookie guards and fit nested launch fixtures * ci: configure the bundled Chromium sandbox helper * fix(browse): classify Playwright authentication timeouts * test: retain bounded Windows lifecycle diagnostics * test(cso): reuse bounded NTFS precision candidates * test(review): handle explicit preservation choices safely * test(browse): remove owned fixture directories with explicit primitives * test(review): distinguish descriptive reuse from edit commitments * test: admit only the approved unscored cookie workflow refusal * test: keep the Office Hours judge mock export-complete * fix: keep dependency-free CI planners independent of the model SDK * test: observe the exact holder after a native fixture unlink failure * fix: start seeded PTY observations at owned readiness * test: acquire identity-bound Windows deletion admission before profile resets * test: preserve qualified Git index bits without authorizing mutations
This commit is contained in:
1 parent
730a1017d1
commit
a84b0b5b6d
111 files changed
+14996
-1057
No files matched your search
@@ -0,0 +1,94 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import { createReadStream } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const NATIVE_QUALIFICATION_DATA = 'browse/src/cookie-import-native-qualification.json';
|
||||
export const NATIVE_BROWSER_VERSION_COMMAND = '$ErrorActionPreference = "Stop"; [Diagnostics.FileVersionInfo]::GetVersionInfo($env:GSTACK_QUALIFY_BROWSER_EXE).ProductVersion';
|
||||
|
||||
export const NATIVE_CODE_INPUTS = Object.freeze([
|
||||
'browse/src/cookie-import-browser.ts',
|
||||
'browse/src/cookie-database.ts',
|
||||
'browse/src/cookie-import-native.ts',
|
||||
'browse/src/cookie-import-native-integrity.ts',
|
||||
'browse/src/cookie-import-native-job.ts',
|
||||
'browse/src/cookie-import-native-worker.ts',
|
||||
'browse/src/bun-polyfill.cjs',
|
||||
'browse/scripts/build-node-server.sh',
|
||||
'.github/scripts/run-cookie-native-qualification.ps1',
|
||||
'browse/dist/server-node.mjs',
|
||||
'browse/dist/bun-polyfill.cjs',
|
||||
'browse/test/cookie-import-native.test.ts',
|
||||
'browse/test/cookie-import-native-job.test.ts',
|
||||
'browse/test/cookie-import-native-qualification.ts',
|
||||
'browse/test/fixtures/native-cookie-process.cjs',
|
||||
'browse/test/fixtures/native-cookie-launch.cjs',
|
||||
'browse/test/fixtures/native-cookie-process-observer.ts',
|
||||
'browse/test/fixtures/native-cookie-file-owners.ts',
|
||||
'browse/test/fixtures/native-cookie-remove-fixture.cjs',
|
||||
'node_modules/playwright/package.json',
|
||||
'node_modules/playwright/index.js',
|
||||
'node_modules/playwright-core/package.json',
|
||||
'node_modules/playwright-core/index.js',
|
||||
'node_modules/playwright-core/lib/bootstrap.js',
|
||||
'node_modules/playwright-core/lib/coreBundle.js',
|
||||
'node_modules/playwright-core/lib/utilsBundle.js',
|
||||
]);
|
||||
|
||||
export interface NativeQualifiedBuild {
|
||||
browserName: 'Chrome' | 'Chromium' | 'Brave' | 'Edge';
|
||||
architecture: 'x64' | 'arm64';
|
||||
windowsRelease: string;
|
||||
executableSha256: string;
|
||||
nodeVersion: string;
|
||||
bunVersion: string;
|
||||
playwrightVersion: string;
|
||||
sourceHashes: Record<string, string>;
|
||||
}
|
||||
|
||||
async function readBoundedFile(file: string, deadline: number, maximumBytes: number): Promise<Buffer> {
|
||||
if (!Number.isFinite(deadline) || Date.now() >= deadline) throw new Error('native_timeout');
|
||||
const cancellation = new AbortController();
|
||||
const timer = setTimeout(() => cancellation.abort(), Math.max(0, deadline - Date.now()));
|
||||
const stream = createReadStream(file, { signal: cancellation.signal });
|
||||
const chunks: Buffer[] = [];
|
||||
let size = 0;
|
||||
try {
|
||||
for await (const chunk of stream) {
|
||||
size += chunk.length;
|
||||
if (size > maximumBytes) throw new Error('native_unqualified');
|
||||
chunks.push(chunk);
|
||||
}
|
||||
if (Date.now() >= deadline) throw new Error('native_timeout');
|
||||
return Buffer.concat(chunks);
|
||||
} catch (error) {
|
||||
if (cancellation.signal.aborted) throw new Error('native_timeout');
|
||||
throw error;
|
||||
} finally {
|
||||
stream.destroy();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
export async function readNativeQualifications(root: string, deadline: number): Promise<NativeQualifiedBuild[]> {
|
||||
const builds = JSON.parse((await readBoundedFile(path.join(root, NATIVE_QUALIFICATION_DATA), deadline, 1024 * 1024)).toString('utf8'));
|
||||
if (!Array.isArray(builds) || builds.some(build => !build || typeof build !== 'object')) throw new Error('native_unqualified');
|
||||
return builds;
|
||||
}
|
||||
|
||||
export async function hashNativeFile(file: string, deadline: number): Promise<string> {
|
||||
return createHash('sha256').update(await readBoundedFile(file, deadline, 64 * 1024 * 1024)).digest('hex');
|
||||
}
|
||||
|
||||
export async function nativeCodeHashes(root: string, deadline: number): Promise<Record<string, string>> {
|
||||
const hashes: Record<string, string> = {};
|
||||
for (const file of NATIVE_CODE_INPUTS) hashes[file] = await hashNativeFile(path.join(root, file), deadline);
|
||||
return hashes;
|
||||
}
|
||||
|
||||
export function nativeCodeMatches(expected: unknown, actual: Record<string, string>): boolean {
|
||||
if (!expected || typeof expected !== 'object' || Array.isArray(expected) || Object.keys(expected).length !== NATIVE_CODE_INPUTS.length) return false;
|
||||
return NATIVE_CODE_INPUTS.every(file => {
|
||||
const hash = (expected as Record<string, unknown>)[file];
|
||||
return typeof hash === 'string' && /^[0-9a-f]{64}$/.test(hash) && hash === actual[file];
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user