Fix CSP vulnerability by replacing quickjs singlefile with wasmfile async variant

Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-08-12 17:51:09 +00:00
parent 268ac9e81b
commit 72a4fd93cd
4 changed files with 14 additions and 14 deletions

8
package-lock.json generated
View file

@ -13,7 +13,7 @@
"@codemirror/language": "^6.10.0", "@codemirror/language": "^6.10.0",
"@codemirror/state": "^6.5.0", "@codemirror/state": "^6.5.0",
"@codemirror/view": "^6.36.0", "@codemirror/view": "^6.36.0",
"@jitl/quickjs-singlefile-browser-release-sync": "^0.32.0", "@jitl/quickjs-wasmfile-release-asyncify": "^0.32.0",
"@lezer/highlight": "^1.2.0", "@lezer/highlight": "^1.2.0",
"@tauri-apps/api": "^2.5.0", "@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-autostart": "^2.3.0", "@tauri-apps/plugin-autostart": "^2.3.0",
@ -540,10 +540,10 @@
"integrity": "sha512-v9T+GQpmk43VDJ7d72sf0Nexhk+ArvtUihW27dy7lqAl0zBObFKtSBBIm5RBjwIhE8VwsPPm9PNuvPvNqLWUEg==", "integrity": "sha512-v9T+GQpmk43VDJ7d72sf0Nexhk+ArvtUihW27dy7lqAl0zBObFKtSBBIm5RBjwIhE8VwsPPm9PNuvPvNqLWUEg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jitl/quickjs-singlefile-browser-release-sync": { "node_modules/@jitl/quickjs-wasmfile-release-asyncify": {
"version": "0.32.0", "version": "0.32.0",
"resolved": "https://registry.npmjs.org/@jitl/quickjs-singlefile-browser-release-sync/-/quickjs-singlefile-browser-release-sync-0.32.0.tgz", "resolved": "https://registry.npmjs.org/@jitl/quickjs-wasmfile-release-asyncify/-/quickjs-wasmfile-release-asyncify-0.32.0.tgz",
"integrity": "sha512-Hfdl7rh8dzxNWFRiYAYNbhn0RMF1/tO6SMH2mUW0aTibqwaAtqPRbi4WkwaIDlhNz8Z4dksJi1Zjl1R54Jsc/Q==", "integrity": "sha512-3oSwPfja12ICz4aIblB58cuY8JlEq5Txt8Cut4VLo+LH47QN+mzCnSgnbB03hWzg1LBcc+VyyI9UOag7a1NF+Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jitl/quickjs-ffi-types": "0.32.0" "@jitl/quickjs-ffi-types": "0.32.0"

View file

@ -19,7 +19,7 @@
"@codemirror/language": "^6.10.0", "@codemirror/language": "^6.10.0",
"@codemirror/state": "^6.5.0", "@codemirror/state": "^6.5.0",
"@codemirror/view": "^6.36.0", "@codemirror/view": "^6.36.0",
"@jitl/quickjs-singlefile-browser-release-sync": "^0.32.0", "@jitl/quickjs-wasmfile-release-asyncify": "^0.32.0",
"@lezer/highlight": "^1.2.0", "@lezer/highlight": "^1.2.0",
"@tauri-apps/api": "^2.5.0", "@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-autostart": "^2.3.0", "@tauri-apps/plugin-autostart": "^2.3.0",

View file

@ -23,7 +23,7 @@
} }
], ],
"security": { "security": {
"csp": "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src ipc: http://ipc.localhost https://open.er-api.com https://api.coingecko.com https://query1.finance.yahoo.com https://query2.finance.yahoo.com https://api.frankfurter.dev" "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src ipc: http://ipc.localhost https://open.er-api.com https://api.coingecko.com https://query1.finance.yahoo.com https://query2.finance.yahoo.com https://api.frankfurter.dev"
} }
}, },
"bundle": { "bundle": {

View file

@ -1,11 +1,11 @@
// JS extensions runtime: numi.setVariable, numi.addUnit, numi.addFunction. // JS extensions runtime: numi.setVariable, numi.addUnit, numi.addFunction.
// Scripts run inside a QuickJS WASM sandbox — no DOM, no Tauri IPC, no host globals. // Scripts run inside a QuickJS WASM sandbox — no DOM, no Tauri IPC, no host globals.
import { import {
newQuickJSWASMModuleFromVariant, newQuickJSAsyncWASMModuleFromVariant,
QuickJSContext, QuickJSAsyncContext,
QuickJSHandle, QuickJSHandle,
} from "quickjs-emscripten-core"; } from "quickjs-emscripten-core";
import releaseSyncVariant from "@jitl/quickjs-singlefile-browser-release-sync"; import releaseAsyncVariant from "@jitl/quickjs-wasmfile-release-asyncify";
import { SumEngine, ExtensionUnitSpec, ExtensionValue } from "./engine"; import { SumEngine, ExtensionUnitSpec, ExtensionValue } from "./engine";
interface ExtensionApi { interface ExtensionApi {
@ -82,7 +82,7 @@ export async function runExtensions(
type RunWithTimeout = <T>(timeoutMs: number, fn: () => T) => T; type RunWithTimeout = <T>(timeoutMs: number, fn: () => T) => T;
function callGuest( function callGuest(
vm: QuickJSContext, vm: QuickJSAsyncContext,
id: string, id: string,
fn: QuickJSHandle, fn: QuickJSHandle,
values: ExtensionValue[], values: ExtensionValue[],
@ -121,7 +121,7 @@ function callGuest(
} }
function exposeApi( function exposeApi(
vm: QuickJSContext, vm: QuickJSAsyncContext,
api: ExtensionApi, api: ExtensionApi,
runWithTimeout: RunWithTimeout, runWithTimeout: RunWithTimeout,
) { ) {
@ -184,7 +184,7 @@ function exposeApi(
} }
function evaluateScripts( function evaluateScripts(
vm: QuickJSContext, vm: QuickJSAsyncContext,
scripts: { name: string; code: string }[], scripts: { name: string; code: string }[],
runWithTimeout: RunWithTimeout, runWithTimeout: RunWithTimeout,
) { ) {
@ -209,8 +209,8 @@ async function load(
engine: SumEngine, engine: SumEngine,
scripts: { name: string; code: string }[], scripts: { name: string; code: string }[],
): Promise<void> { ): Promise<void> {
const mod = await newQuickJSWASMModuleFromVariant(releaseSyncVariant); const mod = await newQuickJSAsyncWASMModuleFromVariant(releaseAsyncVariant);
const vm: QuickJSContext = mod.newContext(); const vm: QuickJSAsyncContext = mod.newContext();
vm.runtime.setMemoryLimit(MEMORY_LIMIT); vm.runtime.setMemoryLimit(MEMORY_LIMIT);
vm.runtime.setMaxStackSize(STACK_SIZE); vm.runtime.setMaxStackSize(STACK_SIZE);