Disallow Object.create() and reflect. (#22408)

This commit is contained in:
Christian Gunderman
2026-03-16 16:24:27 +00:00
committed by GitHub
parent e3df87cf1a
commit ef5627eece
9 changed files with 229 additions and 66 deletions

View File

@@ -77,43 +77,55 @@ export function patchStdio(): () => void {
};
}
/**
* Type guard to check if a property key exists on an object.
*/
function isKey<T extends object>(
key: string | symbol | number,
obj: T,
): key is keyof T {
return key in obj;
}
/**
* Creates proxies for process.stdout and process.stderr that use the real write methods
* (writeToStdout and writeToStderr) bypassing any monkey patching.
* This is used to write to the real output even when stdio is patched.
*/
export function createWorkingStdio() {
const inkStdout = new Proxy(process.stdout, {
get(target, prop, receiver) {
const stdoutHandler: ProxyHandler<typeof process.stdout> = {
get(target, prop) {
if (prop === 'write') {
return writeToStdout;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const value = Reflect.get(target, prop, receiver);
if (typeof value === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return value.bind(target);
if (isKey(prop, target)) {
const value = target[prop];
if (typeof value === 'function') {
return value.bind(target);
}
return value;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return value;
return undefined;
},
});
};
const inkStdout = new Proxy(process.stdout, stdoutHandler);
const inkStderr = new Proxy(process.stderr, {
get(target, prop, receiver) {
const stderrHandler: ProxyHandler<typeof process.stderr> = {
get(target, prop) {
if (prop === 'write') {
return writeToStderr;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const value = Reflect.get(target, prop, receiver);
if (typeof value === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return value.bind(target);
if (isKey(prop, target)) {
const value = target[prop];
if (typeof value === 'function') {
return value.bind(target);
}
return value;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return value;
return undefined;
},
});
};
const inkStderr = new Proxy(process.stderr, stderrHandler);
return { stdout: inkStdout, stderr: inkStderr };
}