web: Don't use direct eval, use indirect new Function(...) instead

This commit is contained in:
Nathan Adams 2024-06-22 23:29:45 +02:00
parent 9979631f8c
commit 575481f9cc
2 changed files with 25 additions and 4 deletions

View File

@ -65,14 +65,13 @@ export function copyToAudioBufferInterleaved(
*
* @internal
*/
// @ts-expect-error defined but not used
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function callExternalInterface(name: string, args: any[]): any {
// [NA] Yes, this is direct eval. Yes, this is a Bad Thing when it comes to security.
// [NA] Yes, this is indirect eval. Yes, this is a Bad Thing when it comes to security.
// In fact, yes this is vulnerable to an XSS attack!
// But plot twist: Flash allowed for this and many games *rely on it*. :(
// Flash content can do `call("eval", "....")` regardless, this doesn't enable anything that wasn't already permitted.
// It just goes against what the documentation says, and *looks* really suspicious.
// Content can only run this if the website has enabled `allowScriptAccess`, so it has to be enabled by the website too.
return eval(`(${name})(...args)`);
return new Function(`return (${name})(...arguments);`)(...args);
}

View File

@ -272,6 +272,28 @@ log called with 1 argument
"does.not.exist"
]
call(does.not.exist, ...) = undefined
`,
);
});
it("doesn't enforce Strict Mode", async () => {
const player = await browser.$("<ruffle-object>");
await browser.execute((player) => {
player.callMethodWithDelay(
"function(){return aPropertyThatDoesntExist = 'success!'}",
);
}, player);
// [NA] Because of the delay, if we fetch immediately we *may* just get part of the log.
await browser.pause(200);
const actualOutput = await getTraceOutput(browser, player);
expect(actualOutput).to.eql(
`callMethodWithDelay called with 1 argument
[
"function(){return aPropertyThatDoesntExist = 'success!'}"
]
call(function(){return aPropertyThatDoesntExist = 'success!'}, ...) = "success!"
`,
);
});