Skip to content

Commit

Permalink
Chore: Increase performance and security of integrations’ scripts (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigok committed May 26, 2022
1 parent cbb0844 commit 6f3133f
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 43 deletions.
41 changes: 21 additions & 20 deletions apps/meteor/app/integrations/server/api/api.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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,
};
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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({
Expand Down
41 changes: 19 additions & 22 deletions apps/meteor/app/integrations/server/lib/triggerHandler.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 = {};
Expand Down Expand Up @@ -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,
};
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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:`,
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 6f3133f

Please sign in to comment.