mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Prevent function module overwriting built-in sandbox properties
This commit is contained in:
parent
9d34abf603
commit
785c349adc
@ -344,6 +344,16 @@
|
|||||||
that.element.val(that.value());
|
that.element.val(that.value());
|
||||||
that.element.trigger('change',that.propertyType,that.value());
|
that.element.trigger('change',that.propertyType,that.value());
|
||||||
});
|
});
|
||||||
|
this.input.on('keyup', function(evt) {
|
||||||
|
that.validate();
|
||||||
|
that.element.val(that.value());
|
||||||
|
that.element.trigger('keyup',evt);
|
||||||
|
});
|
||||||
|
this.input.on('paste', function(evt) {
|
||||||
|
that.validate();
|
||||||
|
that.element.val(that.value());
|
||||||
|
that.element.trigger('paste',evt);
|
||||||
|
});
|
||||||
this.input.on('keydown', function(evt) {
|
this.input.on('keydown', function(evt) {
|
||||||
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
|
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
border-left: none;
|
border-left: none;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
height: 26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-libs-entry > span > i {
|
.node-libs-entry > span > i {
|
||||||
@ -89,6 +94,25 @@
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
var invalidModuleVNames = [
|
||||||
|
'console',
|
||||||
|
'util',
|
||||||
|
'Buffer',
|
||||||
|
'Date',
|
||||||
|
'RED',
|
||||||
|
'node',
|
||||||
|
'__node__',
|
||||||
|
'context',
|
||||||
|
'flow',
|
||||||
|
'global',
|
||||||
|
'env',
|
||||||
|
'setTimeout',
|
||||||
|
'clearTimeout',
|
||||||
|
'setInterval',
|
||||||
|
'clearInterval',
|
||||||
|
'promisify'
|
||||||
|
]
|
||||||
|
|
||||||
var knownFunctionNodes = {};
|
var knownFunctionNodes = {};
|
||||||
RED.events.on("nodes:add", function(n) {
|
RED.events.on("nodes:add", function(n) {
|
||||||
if (n.type === "function") {
|
if (n.type === "function") {
|
||||||
@ -193,6 +217,16 @@
|
|||||||
width: "120px",
|
width: "120px",
|
||||||
"margin-left": "5px"
|
"margin-left": "5px"
|
||||||
}).appendTo(row0).val(opt.var);
|
}).appendTo(row0).val(opt.var);
|
||||||
|
var vnameWarning = $('<span style="display:inline-block; width: 16px;"><i class="fa fa-warning"></i></span>').appendTo(row0);
|
||||||
|
RED.popover.tooltip(vnameWarning.find("i"),function() {
|
||||||
|
var val = fvar.val();
|
||||||
|
if (invalidModuleVNames.indexOf(val) !== -1) {
|
||||||
|
return RED._("node-red:function.error.moduleNameReserved",{name:val})
|
||||||
|
} else {
|
||||||
|
return RED._("node-red:function.error.moduleNameError",{name:val})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
$('<code> = require(</code>').appendTo(row0);
|
$('<code> = require(</code>').appendTo(row0);
|
||||||
var fmodule = $("<input/>", {
|
var fmodule = $("<input/>", {
|
||||||
class: "node-input-libs-val",
|
class: "node-input-libs-val",
|
||||||
@ -210,29 +244,33 @@
|
|||||||
|
|
||||||
$('<code>)</code>').appendTo(row0);
|
$('<code>)</code>').appendTo(row0);
|
||||||
|
|
||||||
var warning = $('<span style="display:inline-block; width: 16px;"><i class="fa fa-warning"></i></span>').appendTo(row0);
|
var moduleWarning = $('<span style="display:inline-block; width: 16px;"><i class="fa fa-warning"></i></span>').appendTo(row0);
|
||||||
RED.popover.tooltip(warning.find("i"),function() {
|
RED.popover.tooltip(moduleWarning.find("i"),function() {
|
||||||
var val = fmodule.typedInput("type");
|
var val = fmodule.typedInput("type");
|
||||||
if (val === "_custom_") {
|
if (val === "_custom_") {
|
||||||
val = fmodule.val();
|
val = fmodule.val();
|
||||||
}
|
}
|
||||||
|
var errors = [];
|
||||||
|
|
||||||
if (!RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList)) {
|
if (!RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList)) {
|
||||||
return "Module not allowed"
|
return RED._("node-red:function.error.moduleNotAllowed",{module:val});
|
||||||
} else {
|
} else {
|
||||||
return "Module not installed: "+missingModuleReasons[val]
|
return RED._("node-red:function.error.moduleLoadError",{module:val,error:missingModuleReasons[val]});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
fvar.on("change", function (e) {
|
fvar.on("change keyup paste", function (e) {
|
||||||
var v = $(this).val().trim();
|
var v = $(this).val().trim();
|
||||||
if (v === "" || / /.test(v)) {
|
if (v === "" || / /.test(v) || invalidModuleVNames.indexOf(v) !== -1) {
|
||||||
fvar.addClass("input-error");
|
fvar.addClass("input-error");
|
||||||
|
vnameWarning.addClass("input-error");
|
||||||
} else {
|
} else {
|
||||||
fvar.removeClass("input-error");
|
fvar.removeClass("input-error");
|
||||||
|
vnameWarning.removeClass("input-error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fmodule.on("change", function (e) {
|
fmodule.on("change keyup paste", function (e) {
|
||||||
var val = $(this).typedInput("type");
|
var val = $(this).typedInput("type");
|
||||||
if (val === "_custom_") {
|
if (val === "_custom_") {
|
||||||
val = $(this).val();
|
val = $(this).val();
|
||||||
@ -243,18 +281,18 @@
|
|||||||
|
|
||||||
if (RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList) && (missingModules.indexOf(val) === -1)) {
|
if (RED.utils.checkModuleAllowed(val,null,installAllowList,installDenyList) && (missingModules.indexOf(val) === -1)) {
|
||||||
fmodule.removeClass("input-error");
|
fmodule.removeClass("input-error");
|
||||||
warning.removeClass("input-error");
|
moduleWarning.removeClass("input-error");
|
||||||
} else {
|
} else {
|
||||||
fmodule.addClass("input-error");
|
fmodule.addClass("input-error");
|
||||||
warning.addClass("input-error");
|
moduleWarning.addClass("input-error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (RED.utils.checkModuleAllowed(opt.module,null,installAllowList,installDenyList) && (missingModules.indexOf(opt.module) === -1)) {
|
if (RED.utils.checkModuleAllowed(opt.module,null,installAllowList,installDenyList) && (missingModules.indexOf(opt.module) === -1)) {
|
||||||
fmodule.removeClass("input-error");
|
fmodule.removeClass("input-error");
|
||||||
warning.removeClass("input-error");
|
moduleWarning.removeClass("input-error");
|
||||||
} else {
|
} else {
|
||||||
fmodule.addClass("input-error");
|
fmodule.addClass("input-error");
|
||||||
warning.addClass("input-error");
|
moduleWarning.addClass("input-error");
|
||||||
}
|
}
|
||||||
if (opt.var) {
|
if (opt.var) {
|
||||||
fvar.trigger("change");
|
fvar.trigger("change");
|
||||||
@ -293,6 +331,9 @@
|
|||||||
if (missingModules.indexOf(m.module) > -1) {
|
if (missingModules.indexOf(m.module) > -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (invalidModuleVNames.indexOf(m.var) !== -1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}}
|
}}
|
||||||
@ -325,15 +366,15 @@
|
|||||||
|
|
||||||
tabs.addTab({
|
tabs.addTab({
|
||||||
id: "func-tab-init",
|
id: "func-tab-init",
|
||||||
label: "On Start", //that._("function.label.initialize")
|
label: that._("function.label.initialize")
|
||||||
});
|
});
|
||||||
tabs.addTab({
|
tabs.addTab({
|
||||||
id: "func-tab-body",
|
id: "func-tab-body",
|
||||||
label: "On Message"//that._("function.label.function")
|
label: that._("function.label.function")
|
||||||
});
|
});
|
||||||
tabs.addTab({
|
tabs.addTab({
|
||||||
id: "func-tab-finalize",
|
id: "func-tab-finalize",
|
||||||
label: "On Stop"//that._("function.label.finalize")
|
label: that._("function.label.finalize")
|
||||||
});
|
});
|
||||||
|
|
||||||
tabs.activateTab("func-tab-body");
|
tabs.activateTab("func-tab-body");
|
||||||
|
@ -273,6 +273,37 @@ module.exports = function(RED) {
|
|||||||
sandbox.promisify = util.promisify;
|
sandbox.promisify = util.promisify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.hasOwnProperty("libs")) {
|
||||||
|
let moduleErrors = false;
|
||||||
|
var modules = node.libs;
|
||||||
|
modules.forEach(module => {
|
||||||
|
var vname = module.hasOwnProperty("var") ? module.var : null;
|
||||||
|
if (vname && (vname !== "")) {
|
||||||
|
if (sandbox.hasOwnProperty(vname) || vname === 'node') {
|
||||||
|
node.error(RED._("function.error.moduleNameError",{name:vname}))
|
||||||
|
moduleErrors = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sandbox[vname] = null;
|
||||||
|
try {
|
||||||
|
var spec = module.module;
|
||||||
|
if (spec && (spec !== "")) {
|
||||||
|
var lib = RED.require(module.module);
|
||||||
|
sandbox[vname] = lib;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
//TODO: NLS error message
|
||||||
|
node.error(RED._("function.error.moduleLoadError",{module:module.spec, error:e.toString()}))
|
||||||
|
moduleErrors = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (moduleErrors) {
|
||||||
|
throw new Error("Function node failed to load external modules");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const RESOLVING = 0;
|
const RESOLVING = 0;
|
||||||
const RESOLVED = 1;
|
const RESOLVED = 1;
|
||||||
const ERROR = 2;
|
const ERROR = 2;
|
||||||
@ -289,26 +320,6 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (node.hasOwnProperty("libs")) {
|
|
||||||
var modules = node.libs;
|
|
||||||
modules.forEach(module => {
|
|
||||||
var vname = module.hasOwnProperty("var") ? module.var : null;
|
|
||||||
if (vname && (vname !== "")) {
|
|
||||||
sandbox[vname] = null;
|
|
||||||
try {
|
|
||||||
var spec = module.module;
|
|
||||||
if (spec && (spec !== "")) {
|
|
||||||
var lib = RED.require(module.module);
|
|
||||||
sandbox[vname] = lib;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
node.warn("failed to load library: "+ module.spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var context = vm.createContext(sandbox);
|
var context = vm.createContext(sandbox);
|
||||||
try {
|
try {
|
||||||
var iniScript = null;
|
var iniScript = null;
|
||||||
|
@ -209,9 +209,9 @@
|
|||||||
"function": {
|
"function": {
|
||||||
"function": "",
|
"function": "",
|
||||||
"label": {
|
"label": {
|
||||||
"function": "Function",
|
"function": "On Message",
|
||||||
"initialize": "Setup",
|
"initialize": "On Start",
|
||||||
"finalize": "Close",
|
"finalize": "On Stop",
|
||||||
"outputs": "Outputs",
|
"outputs": "Outputs",
|
||||||
"require": "Require"
|
"require": "Require"
|
||||||
},
|
},
|
||||||
@ -224,6 +224,10 @@
|
|||||||
"module": "module"
|
"module": "module"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
"moduleNotAllowed": "Module __module__ not allowed",
|
||||||
|
"moduleLoadError": "Failed to load module __module__: __error__",
|
||||||
|
"moduleNameError": "Invalid module variable name: __name__",
|
||||||
|
"moduleNameReserved": "Reserved variable name: __name__",
|
||||||
"inputListener":"Cannot add listener to 'input' event within Function",
|
"inputListener":"Cannot add listener to 'input' event within Function",
|
||||||
"non-message-returned":"Function tried to send a message of type __type__"
|
"non-message-returned":"Function tried to send a message of type __type__"
|
||||||
}
|
}
|
||||||
|
@ -1438,7 +1438,6 @@ describe('function node', function() {
|
|||||||
}
|
}
|
||||||
},20);
|
},20);
|
||||||
}).catch(err => done(err));
|
}).catch(err => done(err));
|
||||||
|
|
||||||
})
|
})
|
||||||
it('should require the OS module', function(done) {
|
it('should require the OS module', function(done) {
|
||||||
var flow = [
|
var flow = [
|
||||||
@ -1459,9 +1458,18 @@ describe('function node', function() {
|
|||||||
});
|
});
|
||||||
n1.receive({payload:"foo",topic: "bar"});
|
n1.receive({payload:"foo",topic: "bar"});
|
||||||
}).catch(err => done(err));
|
}).catch(err => done(err));
|
||||||
|
|
||||||
})
|
})
|
||||||
|
it('should fail if module variable name clashes with sandbox builtin', function(done) {
|
||||||
|
var flow = [
|
||||||
|
{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = os.type(); return msg;", "libs": [{var:"flow", module:"os"}]},
|
||||||
|
{id:"n2", type:"helper"}
|
||||||
|
];
|
||||||
|
helper.load(functionNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
should.not.exist(n1);
|
||||||
|
done();
|
||||||
|
}).catch(err => done(err));
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ describe("externalModules api", function() {
|
|||||||
it("installs missing modules", async function() {
|
it("installs missing modules", async function() {
|
||||||
externalModules.init({userDir: homeDir});
|
externalModules.init({userDir: homeDir});
|
||||||
externalModules.register("function", "libs");
|
externalModules.register("function", "libs");
|
||||||
fs.existsSync(path.join(homeDir,"externalModuels")).should.be.false();
|
fs.existsSync(path.join(homeDir,"externalModules")).should.be.false();
|
||||||
await externalModules.checkFlowDependencies([
|
await externalModules.checkFlowDependencies([
|
||||||
{type: "function", libs:[{module: "foo"}]}
|
{type: "function", libs:[{module: "foo"}]}
|
||||||
])
|
])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user