🐛 document proxy in strict sandbox mode replaces receiver with target in methods args (#2450)

This commit is contained in:
Umberto Toniolo 2023-04-13 06:09:18 +02:00 committed by GitHub
parent 38fa818273
commit 8bb5c948be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 2 deletions

View File

@ -0,0 +1,53 @@
import { SandBoxType } from '../../../../interfaces';
import { noop } from 'lodash';
import { patchStrictSandbox } from '../forStrictSandbox';
jest.mock('import-html-entry', () => ({
execScripts: jest.fn(),
}));
describe('forStrictSandbox test', () => {
const {
prototype: { createTreeWalker: originalCreateTreeWalker },
} = Document;
beforeAll(() => {
Document.prototype.createTreeWalker = function createTreeWalker(
this: Document,
root: Node,
whatToShow?: number | undefined,
filter?: NodeFilter | null | undefined,
) {
if (document !== root) {
throw new TypeError('error');
}
return originalCreateTreeWalker.call(this, root, whatToShow, filter);
};
});
afterAll(() => {
Document.prototype.createTreeWalker = originalCreateTreeWalker;
});
it('should not throw on patched document', () => {
let patchedDocument!: Document;
const appName = 'test-app';
const wrapper = document.createElement('div');
const sandbox = {
name: appName,
type: SandBoxType.Proxy,
proxy: window,
sandboxRunning: true,
latestSetProp: null,
patchDocument: (patched: Document) => {
patchedDocument = patched;
},
active: noop,
inactive: noop,
};
patchStrictSandbox(appName, () => wrapper, sandbox, true, false, undefined, true);
expect(patchedDocument).toBeDefined();
expect(() => patchedDocument?.createTreeWalker(patchedDocument)).not.toThrow();
});
});

View File

@ -53,7 +53,7 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) {
(<any>target)[p] = value;
return true;
},
get: (target, p) => {
get: (target, p, receiver) => {
if (p === 'createElement') {
// Must store the original createElement function to avoid error in nested sandbox
const targetCreateElement = target.createElement;
@ -67,7 +67,9 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) {
const value = (<any>target)[p];
// must rebind the function to the target otherwise it will cause illegal invocation error
if (typeof value === 'function' && !isBoundedFunction(value)) {
return value.bind(target);
return function proxiedFunction(...args: unknown[]) {
return value.call(target, ...args.map((arg) => (arg === receiver ? target : arg)));
};
}
return value;