Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,9 @@ const modify_request = (ctx, new_req) => {
ctx.rq_request_body = new_req;
};
const modify_request_using_code = async (action, ctx) => {
let userFunction = null;
try {
userFunction = (0, utils_2.getFunctionFromString)(action.request);
}
catch (error) {
// User has provided an invalid function
return modify_request(ctx, "Can't parse Requestly function. Please recheck. Error Code 7201. Actual Error: " +
error.message);
}
if (!userFunction || typeof userFunction !== "function") {
// RQ-2426: validate the function source parses (compile-only, no execution)
// before running it in the sandboxed worker.
if (!(await (0, utils_2.isValidFunctionString)(action.request))) {
// User has provided an invalid function
return modify_request(ctx, "Can't parse Requestly function. Please recheck. Error Code 944.");
}
Expand All @@ -58,7 +51,7 @@ const modify_request_using_code = async (action, ctx) => {
catch (_a) {
/*Do nothing -- could not parse body as JSON */
}
finalRequest = await (0, utils_2.executeUserFunction)(ctx, userFunction, args);
finalRequest = await (0, utils_2.executeUserFunction)(ctx, action.request, args);
if (finalRequest && typeof finalRequest === "string") {
return modify_request(ctx, finalRequest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,9 @@ const modify_response_using_local = (action, ctx) => {
};
const modify_response_using_code = async (action, ctx) => {
var _a, _b, _c, _d;
let userFunction = null;
try {
userFunction = (0, utils_2.getFunctionFromString)(action.response);
}
catch (error) {
// User has provided an invalid function
return modify_response(ctx, "Can't parse Requestly function. Please recheck. Error Code 7201. Actual Error: " +
error.message);
}
if (!userFunction || typeof userFunction !== "function") {
// RQ-2426: validate the function source parses (compile-only, no execution)
// before running it in the sandboxed worker.
if (!(await (0, utils_2.isValidFunctionString)(action.response))) {
// User has provided an invalid function
return modify_response(ctx, "Can't parse Requestly function. Please recheck. Error Code 944.");
}
Expand Down
9 changes: 8 additions & 1 deletion dist/utils/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
export declare const getFunctionFromString: (functionStringEscaped: any) => any;
/**
* Verify a rule's code string parses WITHOUT executing it. Constructing
* `new Function(body)` compiles/parses the body but never runs it (the function
* is never called), so even an IIFE-shaped string cannot execute here. Avoids the
* `vm` module (unsupported in Electron's renderer); the sandboxed execution
* happens inside QuickJS.
*/
export declare const isValidFunctionString: (functionStringEscaped: string) => Promise<boolean>;
export declare function executeUserFunction(ctx: any, functionString: string, args: any): Promise<any>;
384 changes: 348 additions & 36 deletions dist/utils/index.js

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions dist/utils/sandbox-globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* sandbox-globals — the JavaScript SOURCE that runs INSIDE the QuickJS guest realm.
*
* These are plain strings injected into the sandbox; nothing here executes in the
* host. `index.ts` owns the host side (module/context lifecycle, the
* crypto/fetch/timer bridges, the pump loop).
*
* Organised by concern, each an IIFE that augments `globalThis` (except HARNESS,
* which must stay top-level so its `var`/`function` bindings are script-global).
* They are concatenated in DEPENDENCY ORDER into `SANDBOX_PRELUDE`:
*
* ENCODING atob/btoa, TextEncoder/Decoder, shared byte helpers (__rqb)
* BINARY Buffer, Blob (use __rqb)
* URL URL, URLSearchParams
* HTTP_TYPES Headers, FormData, Request, Response
* CLONE structuredClone
* CRYPTO crypto.* + require() [host bridge: __hostCrypto]
* NETWORK fetch, XMLHttpRequest, WebSocket [host bridge: __hostFetch]
* TIMERS setTimeout/setInterval/…, performance [host bridge: __hostTimer]
* HARNESS console + args/$sharedState/__OUTPUT (top-level; reads host-injected
* __argsJson/__sharedStateJson; the user fn wrapper runs after it)
*
* Security: pure shims never touch the host. The bridged blocks (CRYPTO/NETWORK/
* TIMERS) call host functions that take and return only JSON-serialisable data —
* no host object is ever handed to the guest, so there is no escape surface.
* `String.raw` keeps regex/`\r\n` backslashes literal so they reach the sandbox JS.
*/
/**
* The complete in-guest prelude, concatenated in dependency order. index.ts
* appends the user-function wrapper after this.
*/
export declare const SANDBOX_PRELUDE: string;
Loading
Loading