UNPKG

sandman

Version:

Sandbox for executing (somewhat) untrusted code

367 lines (335 loc) 12 kB
var realFs = require('fs') , testPath = require('../utils').testPath , Stream = require('stream').Stream , Readable = Stream.Readable , Writable = Stream.Writable; module.exports = rootFs; var notImplemented = function () { throw new Error("Not Implemented"); }; function rootFs(root) { var fs = {}; fs.rename = function (oldPath, newPath, callback) { if(!testPath(oldPath, root)) { return callback(new Error(oldPath + " is outside the root.")); } if(!testPath(newPath, root)) { return callback(new Error(newPath + " is outside the root.")); } return realFs.rename.apply(realFs, [].slice.call(arguments)); }; fs.renameSync = function (oldPath, newPath) { if(!testPath(oldPath, root)) { throw new Error(oldPath + " is outside the root."); } if(!testPath(newPath, root)) { throw new Error(newPath + " is outside the root."); } return realFs.renameSync.apply(realFs, [].slice.call(arguments)); }; fs.ftruncate = notImplemented; fs.ftruncateSync = notImplemented; fs.truncate = function (path, len, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.truncate.apply(realFs, [].slice.call(arguments)); }; fs.truncateSync = function (path, len) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.truncateSync.apply(realFs, [].slice.call(arguments)); }; fs.chown = function (path, uid, gid, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.chown.apply(realFs, [].slice.call(arguments)); }; fs.chownSync = function (path, uid, gid) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.chownSync.apply(realFs, [].slice.call(arguments)); }; fs.fchown = notImplemented; fs.fchownSync = notImplemented; fs.lchown = function (path, uid, gid, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.lchown.apply(realFs, [].slice.call(arguments)); }; fs.lchownSync = function (path, uid, gid) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.lchownSync.apply(realFs, [].slice.call(arguments)); }; fs.chmod = function (path, mode, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.chmod.apply(realFs, [].slice.call(arguments)); }; fs.chmodSync = function (path, mode) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.chmodSync.apply(realFs, [].slice.call(arguments)); }; fs.fchmod = notImplemented; fs.fchmodSync = notImplemented; fs.lchmod = function (path, mode, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.lchmod.apply(realFs, [].slice.call(arguments)); }; fs.lchmodSync = function (path, mode) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.lchmodSync.apply(realFs, [].slice.call(arguments)); }; fs.stat = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.stat.apply(realFs, [].slice.call(arguments)); }; fs.statSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.statSync.apply(realFs, [].slice.call(arguments)); }; fs.lstat = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.lstat.apply(realFs, [].slice.call(arguments)); }; fs.lstatSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.lstatSync.apply(realFs, [].slice.call(arguments)); }; // file descriptors fs.fstat = notImplemented; fs.fstatSync = notImplemented; fs.link = function (srcPath, destPath, callback) { if(!testPath(srcPath, root)) { return callback(new Error(srcPath + " is outside the root.")); } if(!testPath(destPath, root)) { return callback(new Error(destPath + " is outside the root.")); } return realFs.link.apply(realFs, [].slice.call(arguments)); }; fs.linkSync = function (srcPath, destPath, callback) { if(!testPath(srcPath, root)) { throw new Error(srcPath + " is outside the root."); } if(!testPath(destPath, root)) { throw new Error(destPath + " is outside the root."); } return realFs.linkSync.apply(realFs, [].slice.call(arguments)); }; fs.symlink = function (srcPath, destPath, type_, callback) { callback = arguments[arguments.length - 1]; if(!testPath(srcPath, root)) { return callback(new Error(srcPath + " is outside the root.")); } if(!testPath(destPath, root)) { return callback(new Error(destPath + " is outside the root.")); } return realFs.symlink.apply(realFs, [].slice.call(arguments)); }; fs.symlinkSync = function (srcPath, destPath, type_) { if(!testPath(srcPath, root)) { throw new Error(srcPath + " is outside the root."); } if(!testPath(destPath, root)) { throw new Error(destPath + " is outside the root."); } return realFs.symlinkSync.apply(realFs, [].slice.call(arguments)); }; fs.readlink = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.readlink.apply(realFs, [].slice.call(arguments)); }; fs.readlinkSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.readlinkSync.apply(realFs, [].slice.call(arguments)); }; fs.realpath = function (path, cache, callback) { callback = arguments[arguments.length - 1]; if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.realpath.apply(realFs, [].slice.call(arguments)); }; fs.realpathSync = function (path, cache) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.realpathSync.apply(realFs, [].slice.call(arguments)); }; fs.unlink = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.unlink.apply(realFs, [].slice.call(arguments)); }; fs.unlinkSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.unlinkSync.apply(realFs, [].slice.call(arguments)); }; fs.rmdir = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.rmdir.apply(realFs, [].slice.call(arguments)); }; fs.rmdirSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.rmdirSync.apply(realFs, [].slice.call(arguments)); }; fs.mkdir = function (path, mode_, callback) { callback = arguments[arguments.length - 1]; if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.mkdir.apply(realFs, [].slice.call(arguments)); }; fs.mkdirSync = function (path, mode_) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.mkdirSync.apply(realFs, [].slice.call(arguments)); }; fs.readdir = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.readdir.apply(realFs, [].slice.call(arguments)); }; fs.readdirSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.readdirSync.apply(realFs, [].slice.call(arguments)); }; // file descriptors fs.close = notImplemented; fs.closeSync = notImplemented; fs.open = notImplemented; fs.openSync = notImplemented; fs.utimes = function (path, atime, mtime, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.utimes.apply(realFs, [].slice.call(arguments)); }; fs.utimesSync = function (path, atime, mtime) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.utimesSync.apply(realFs, [].slice.call(arguments)); }; // file descriptors fs.futimes = notImplemented; fs.futimesSync = notImplemented; fs.fsync = notImplemented; fs.fsyncSync = notImplemented; fs.write = notImplemented; fs.writeSync = notImplemented; fs.read = notImplemented; fs.readSync = notImplemented; fs.readFile = function (path, options_, callback) { callback = arguments[arguments.length - 1]; if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.readFile.apply(realFs, [].slice.call(arguments)); }; fs.readFileSync = function (path, options_) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.readFileSync.apply(realFs, [].slice.call(arguments)); }; fs.writeFile = function (path, data, options_, callback) { callback = arguments[arguments.length - 1]; if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.writeFile.apply(realFs, [].slice.call(arguments)); }; fs.writeFileSync = function (path, data, options_) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.writeFileSync.apply(realFs, [].slice.call(arguments)); }; fs.appendFile = function (path, data, options_, callback) { callback = arguments[arguments.length - 1]; if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.appendFile.apply(realFs, [].slice.call(arguments)); }; fs.appendFileSync = function (path, data, options_) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.appendFileSync.apply(realFs, [].slice.call(arguments)); }; fs.watchFile = notImplemented; fs.unwatchFile = notImplemented; fs.watch = notImplemented; fs.exists = function (path, callback) { if(!testPath(path, root)) { return callback(new Error(path + " is outside the root.")); } return realFs.exists.apply(realFs, [].slice.call(arguments)); }; fs.existsSync = function (path) { if(!testPath(path, root)) { throw new Error(path + " is outside the root."); } return realFs.existsSync.apply(realFs, [].slice.call(arguments)); }; fs.createReadStream = function (path, options_) { if(!testPath(path, root)) { var stream = new Readable(); process.nextTick(function () { stream.emit('error', new Error(path + " is outside the root.")); }); return stream; } return realFs.createReadStream.apply(realFs, [].slice.call(arguments)); }; fs.createWriteStream = function (path, options_) { if(!testPath(path, root)) { var stream = new Writable(); process.nextTick(function () { stream.emit('error', new Error(path + " is outside the root.")); }); return stream; } return realFs.createWriteStream.apply(realFs, [].slice.call(arguments)); }; return fs; }