Open pierre-b opened 10 years ago
We do not have a sandbox. I would love to have this feature, but I don't have time to work on it. A PR would be awesome :)
Actually let's leave this open as a feature
@jlongster I know that you do not work on this project anymore, but could you tell me how would you go about implementing the sandbox environment? Anything would be really helpful! There are so many things that one could do to break out of sandbox 😞
In node, you could use a package such as vm2 to render untrusted nunjucks templates inside an isolated execution context.
Exemple of problem : https://github.com/mozilla/nunjucks/issues/1048#issuecomment-355869811
This can prevent with hasOwnProperty
.
I wonder if we can make a change, a full security change. Is it possible make a change afterwards ? I mean the code wasn't designed to be safe/sandboxed.
I'm unconvinced vm2 fully solves it.
nunjucks requires fs, events, and path to be available and the eval option to be set to true in a NodeVM in order to execute. the available examples I've found and played with still allow access to .constructor (I think as a result of eval:true ?) and as such allow RCE, although vaguely restricted.
The example available in the referenced thread above still works in a vm2 sandbox:
{{ (0).toString.constructor("return global.process.versions")() | dump | safe }}
though it does seem to resolve this, claiming require isn't available:
{{ "".constructor.__proto__.constructor("return require(`fs`).readFileSync(`Users/squirrelchew/.aws/credentials`, `utf8`)")() }}
Hello,
I ran into this issue recently and came with a solution using isolated-vm and the built version of nunjucks. It allows to render template in isolated secure env.
const ivm = require('isolated-vm');
const fs = require('fs');
const directNunjucks = require('nunjucks');
const isolate = new ivm.Isolate({ memoryLimit: 128 });
const codeNunjucks = fs.readFileSync(__dirname + '/node_modules/nunjucks/browser/nunjucks.min.js', 'utf8');
//we need to wrap the nunjucks browser code with a 'self' context
const isolatedModuleCode = `let self = {};
${codeNunjucks}
export default self;`;
const module1 = isolate.compileModuleSync(isolatedModuleCode);
const context = isolate.createContextSync();
module1.instantiateSync(context, (specifier, mod) => {
return mod;
});
module1.evaluateSync();
const modref = module1.namespace.getSync('default');
const nunjucksIsolated = modref.getSync('nunjucks')
const nunjucksIsolatedRS = nunjucksIsolated.getSync('renderString')
//---
const template = 'zzzz {{ val }} {{ (0).toString.constructor("return global.process.versions")() | dump | safe }}';
const data = { val : 'test'};
const direct = directNunjucks.renderString(template, data);
console.log(direct); // will ouput sensitive data
const isolatedResult = nunjucksIsolatedRS(template, data);// will fail
console.log(isolatedResult);
But you might lose some important nunjucks features, for example you will get no access to the filesystem. Imagine running nunjucks into a limited browser context.
@huggingface/jinja
might help for some use cases as well
Hello everyone,
Could you please tell me if it's possible to sandbox the environment ? Users of my app will be allowed to customize their own emails templates and I would like to restrict some features.
Here is how Twig handles that: http://twig.sensiolabs.org/doc/api.html#sandbox-extension
Thanks