diff --git a/apps/meteor/app/integrations/server/api/api.js b/apps/meteor/app/integrations/server/api/api.js index dd5d9967467..57a4c2b132b 100644 --- a/apps/meteor/app/integrations/server/api/api.js +++ b/apps/meteor/app/integrations/server/api/api.js @@ -1,5 +1,4 @@ -import vm from 'vm'; - +import { VM, VMScript } from 'vm2'; import { Meteor } from 'meteor/meteor'; import { HTTP } from 'meteor/http'; import { Random } from 'meteor/random'; @@ -71,11 +70,16 @@ function getIntegrationScript(integration) { incomingLogger.info({ msg: 'Will evaluate script of Trigger', name: integration.name }); incomingLogger.debug(script); - const vmScript = vm.createScript(script, 'script.js'); - vmScript.runInNewContext(sandbox); - if (sandbox.Script) { + const vmScript = new VMScript(`${script}; Script;`, 'script.js'); + const vm = new VM({ + sandbox, + }); + + const ScriptClass = vm.run(vmScript); + + if (ScriptClass) { compiledScripts[integration._id] = { - script: new sandbox.Script(), + script: new ScriptClass(), store, _updatedAt: integration._updatedAt, }; @@ -92,10 +96,8 @@ function getIntegrationScript(integration) { throw API.v1.failure('error-evaluating-script'); } - if (!sandbox.Script) { - incomingLogger.error({ msg: 'Class "Script" not in Trigger', name: integration.name }); - throw API.v1.failure('class-script-not-found'); - } + incomingLogger.error({ msg: 'Class "Script" not in Trigger', name: integration.name }); + throw API.v1.failure('class-script-not-found'); } function createIntegration(options, user) { @@ -205,9 +207,12 @@ function executeIntegrationRest() { sandbox.script = script; sandbox.request = request; - const result = Future.fromPromise( - vm.runInNewContext( - ` + const vm = new VM({ + timeout: 3000, + sandbox, + }); + + const scriptResult = vm.run(` new Promise((resolve, reject) => { Fiber(() => { scriptTimeout(reject); @@ -218,13 +223,9 @@ function executeIntegrationRest() { } }).run(); }).catch((error) => { throw new Error(error); }); - `, - sandbox, - { - timeout: 3000, - }, - ), - ).wait(); + `); + + const result = Future.fromPromise(scriptResult).wait(); if (!result) { incomingLogger.debug({ diff --git a/apps/meteor/app/integrations/server/lib/triggerHandler.js b/apps/meteor/app/integrations/server/lib/triggerHandler.js index 576c6307141..bc78c8595b8 100644 --- a/apps/meteor/app/integrations/server/lib/triggerHandler.js +++ b/apps/meteor/app/integrations/server/lib/triggerHandler.js @@ -1,5 +1,4 @@ -import vm from 'vm'; - +import { VM, VMScript } from 'vm2'; import { Meteor } from 'meteor/meteor'; import { Random } from 'meteor/random'; import { HTTP } from 'meteor/http'; @@ -19,7 +18,6 @@ import { fetch } from '../../../../server/lib/http/fetch'; export class RocketChatIntegrationHandler { constructor() { - this.vm = vm; this.successResults = [200, 201, 202]; this.compiledScripts = {}; this.triggers = {}; @@ -275,18 +273,20 @@ export class RocketChatIntegrationHandler { const script = integration.scriptCompiled; const { store, sandbox } = this.buildSandbox(); - let vmScript; try { outgoingLogger.info({ msg: 'Will evaluate script of Trigger', name: integration.name }); outgoingLogger.debug(script); - vmScript = this.vm.createScript(script, 'script.js'); + const vmScript = new VMScript(`${script}; Script;`, 'script.js'); + const vm = new VM({ + sandbox, + }); - vmScript.runInNewContext(sandbox); + const ScriptClass = vm.run(vmScript); - if (sandbox.Script) { + if (ScriptClass) { this.compiledScripts[integration._id] = { - script: new sandbox.Script(), + script: new ScriptClass(), store, _updatedAt: integration._updatedAt, }; @@ -303,10 +303,8 @@ export class RocketChatIntegrationHandler { throw new Meteor.Error('error-evaluating-script'); } - if (!sandbox.Script) { - outgoingLogger.error(`Class "Script" not in Trigger ${integration.name}:`); - throw new Meteor.Error('class-script-not-found'); - } + outgoingLogger.error(`Class "Script" not in Trigger ${integration.name}:`); + throw new Meteor.Error('class-script-not-found'); } hasScriptAndMethod(integration, method) { @@ -352,9 +350,12 @@ export class RocketChatIntegrationHandler { this.updateHistory({ historyId, step: `execute-script-before-running-${method}` }); - const result = Future.fromPromise( - this.vm.runInNewContext( - ` + const vm = new VM({ + timeout: 3000, + sandbox, + }); + + const scriptResult = vm.run(` new Promise((resolve, reject) => { Fiber(() => { scriptTimeout(reject); @@ -365,13 +366,9 @@ export class RocketChatIntegrationHandler { } }).run(); }).catch((error) => { throw new Error(error); }); - `, - sandbox, - { - timeout: 3000, - }, - ), - ).wait(); + `); + + const result = Future.fromPromise(scriptResult).wait(); outgoingLogger.debug({ msg: `Script method "${method}" result of the Integration "${integration.name}" is:`, diff --git a/apps/meteor/package.json b/apps/meteor/package.json index aa156264c5b..3a8d33ab60d 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -350,6 +350,7 @@ "url-polyfill": "^1.1.12", "use-subscription": "~1.6.0", "uuid": "^8.3.2", + "vm2": "^3.9.9", "webdav": "^4.9.0", "xml-crypto": "^2.1.3", "xml-encryption": "2.0.0", diff --git a/yarn.lock b/yarn.lock index c80b0d55230..48978808ce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4989,6 +4989,7 @@ __metadata: url-polyfill: ^1.1.12 use-subscription: ~1.6.0 uuid: ^8.3.2 + vm2: ^3.9.9 webdav: ^4.9.0 webpack: ^4.46.0 xml-crypto: ^2.1.3 @@ -33987,7 +33988,7 @@ __metadata: languageName: node linkType: hard -"vm2@npm:^3.9.8": +"vm2@npm:^3.9.8, vm2@npm:^3.9.9": version: 3.9.9 resolution: "vm2@npm:3.9.9" dependencies: