mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Restrict project file access to inside the project directory
This commit is contained in:
parent
7bde7f0cfd
commit
74db3e17d0
@ -305,6 +305,9 @@ Project.prototype.update = function (user, data) {
|
|||||||
return Promise.reject("Invalid package file: "+data.files.package)
|
return Promise.reject("Invalid package file: "+data.files.package)
|
||||||
}
|
}
|
||||||
var root = data.files.package.substring(0,data.files.package.length-12);
|
var root = data.files.package.substring(0,data.files.package.length-12);
|
||||||
|
if (/^\.\./.test(fspath.relative(this.path,fspath.join(this.path,data.files.package)))) {
|
||||||
|
return Promise.reject("Invalid package file: "+data.files.package)
|
||||||
|
}
|
||||||
this.paths.root = root;
|
this.paths.root = root;
|
||||||
this.paths['package.json'] = data.files.package;
|
this.paths['package.json'] = data.files.package;
|
||||||
globalProjectSettings.projects[this.name].rootPath = root;
|
globalProjectSettings.projects[this.name].rootPath = root;
|
||||||
@ -322,12 +325,18 @@ Project.prototype.update = function (user, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.files.hasOwnProperty('flow') && this.package['node-red'].settings.flowFile !== data.files.flow.substring(this.paths.root.length)) {
|
if (data.files.hasOwnProperty('flow') && this.package['node-red'].settings.flowFile !== data.files.flow.substring(this.paths.root.length)) {
|
||||||
|
if (/^\.\./.test(fspath.relative(this.path,fspath.join(this.path,data.files.flow)))) {
|
||||||
|
return Promise.reject("Invalid flow file: "+data.files.flow)
|
||||||
|
}
|
||||||
this.paths.flowFile = data.files.flow;
|
this.paths.flowFile = data.files.flow;
|
||||||
this.package['node-red'].settings.flowFile = data.files.flow.substring(this.paths.root.length);
|
this.package['node-red'].settings.flowFile = data.files.flow.substring(this.paths.root.length);
|
||||||
savePackage = true;
|
savePackage = true;
|
||||||
flowFilesChanged = true;
|
flowFilesChanged = true;
|
||||||
}
|
}
|
||||||
if (data.files.hasOwnProperty('credentials') && this.package['node-red'].settings.credentialsFile !== data.files.credentials.substring(this.paths.root.length)) {
|
if (data.files.hasOwnProperty('credentials') && this.package['node-red'].settings.credentialsFile !== data.files.credentials.substring(this.paths.root.length)) {
|
||||||
|
if (/^\.\./.test(fspath.relative(this.path,fspath.join(this.path,data.files.credentials)))) {
|
||||||
|
return Promise.reject("Invalid credentials file: "+data.files.credentials)
|
||||||
|
}
|
||||||
this.paths.credentialsFile = data.files.credentials;
|
this.paths.credentialsFile = data.files.credentials;
|
||||||
this.package['node-red'].settings.credentialsFile = data.files.credentials.substring(this.paths.root.length);
|
this.package['node-red'].settings.credentialsFile = data.files.credentials.substring(this.paths.root.length);
|
||||||
// Don't know if the credSecret is invalid or not so clear the flag
|
// Don't know if the credSecret is invalid or not so clear the flag
|
||||||
@ -490,6 +499,10 @@ Project.prototype.getFile = function (filePath,treeish) {
|
|||||||
if (treeish !== "_") {
|
if (treeish !== "_") {
|
||||||
return gitTools.getFile(this.path, filePath, treeish);
|
return gitTools.getFile(this.path, filePath, treeish);
|
||||||
} else {
|
} else {
|
||||||
|
let fullPath = fspath.join(this.path,filePath);
|
||||||
|
if (/^\.\./.test(fspath.relative(this.path,fullPath))) {
|
||||||
|
throw new Error("Invalid file name")
|
||||||
|
}
|
||||||
return fs.readFile(fspath.join(this.path,filePath),"utf8");
|
return fs.readFile(fspath.join(this.path,filePath),"utf8");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -639,6 +652,11 @@ Project.prototype.pull = function (user,remoteBranchName,setRemote,allowUnrelate
|
|||||||
|
|
||||||
Project.prototype.resolveMerge = function (file,resolutions) {
|
Project.prototype.resolveMerge = function (file,resolutions) {
|
||||||
var filePath = fspath.join(this.path,file);
|
var filePath = fspath.join(this.path,file);
|
||||||
|
|
||||||
|
if (/^\.\./.test(fspath.relative(this.path,filePath))) {
|
||||||
|
throw new Error("Invalid file name")
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
if (typeof resolutions === 'string') {
|
if (typeof resolutions === 'string') {
|
||||||
return util.writeFile(filePath, resolutions).then(function() {
|
return util.writeFile(filePath, resolutions).then(function() {
|
||||||
@ -1062,7 +1080,7 @@ function loadProject(projectPath) {
|
|||||||
function init(_settings, _runtime) {
|
function init(_settings, _runtime) {
|
||||||
settings = _settings;
|
settings = _settings;
|
||||||
runtime = _runtime;
|
runtime = _runtime;
|
||||||
projectsDir = fspath.join(settings.userDir,"projects");
|
projectsDir = fspath.resolve(fspath.join(settings.userDir,"projects"));
|
||||||
authCache.init();
|
authCache.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ function init(_settings, _runtime) {
|
|||||||
globalGitUser = gitConfig.user;
|
globalGitUser = gitConfig.user;
|
||||||
Projects.init(settings,runtime);
|
Projects.init(settings,runtime);
|
||||||
sshTools.init(settings);
|
sshTools.init(settings);
|
||||||
projectsDir = fspath.join(settings.userDir,"projects");
|
projectsDir = fspath.resolve(fspath.join(settings.userDir,"projects"));
|
||||||
if (!settings.readOnly) {
|
if (!settings.readOnly) {
|
||||||
return fs.ensureDir(projectsDir)
|
return fs.ensureDir(projectsDir)
|
||||||
//TODO: this is accessing settings from storage directly as settings
|
//TODO: this is accessing settings from storage directly as settings
|
||||||
@ -207,9 +207,16 @@ function getBackupFilename(filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadProject(name) {
|
function loadProject(name) {
|
||||||
|
let fullPath = fspath.resolve(fspath.join(projectsDir,name));
|
||||||
var projectPath = name;
|
var projectPath = name;
|
||||||
if (projectPath.indexOf(fspath.sep) === -1) {
|
if (projectPath.indexOf(fspath.sep) === -1) {
|
||||||
projectPath = fspath.join(projectsDir,name);
|
projectPath = fullPath;
|
||||||
|
} else {
|
||||||
|
// Ensure this project dir is under projectsDir;
|
||||||
|
let relativePath = fspath.relative(projectsDir,fullPath);
|
||||||
|
if (/^\.\./.test(relativePath)) {
|
||||||
|
throw new Error("Invalid project name")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Projects.load(projectPath).then(function(project) {
|
return Projects.load(projectPath).then(function(project) {
|
||||||
activeProject = project;
|
activeProject = project;
|
||||||
@ -234,6 +241,10 @@ function deleteProject(user, name) {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
var projectPath = fspath.join(projectsDir,name);
|
var projectPath = fspath.join(projectsDir,name);
|
||||||
|
let relativePath = fspath.relative(projectsDir,projectPath);
|
||||||
|
if (/^\.\./.test(relativePath)) {
|
||||||
|
throw new Error("Invalid project name")
|
||||||
|
}
|
||||||
return Projects.delete(user, projectPath);
|
return Projects.delete(user, projectPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +403,10 @@ function createProject(user, metadata) {
|
|||||||
metadata.files.credentialSecret = currentEncryptionKey;
|
metadata.files.credentialSecret = currentEncryptionKey;
|
||||||
}
|
}
|
||||||
metadata.path = fspath.join(projectsDir,metadata.name);
|
metadata.path = fspath.join(projectsDir,metadata.name);
|
||||||
|
if (/^\.\./.test(fspath.relative(projectsDir,metadata.path))) {
|
||||||
|
throw new Error("Invalid project name")
|
||||||
|
}
|
||||||
|
|
||||||
return Projects.create(user, metadata).then(function(p) {
|
return Projects.create(user, metadata).then(function(p) {
|
||||||
return setActiveProject(user, p.name);
|
return setActiveProject(user, p.name);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user