Recently I stumbled across a vulnerability in doT.js. The vulnerability exists because attackers can use prototype pollution to modify the values of the options passed in to doT.
Example:
var doT = require("dot");
var tempFn = doT.template("<h1>Here is a sample template " +
"{{=console.log(23)}}</h1>");
tempFn({})
var doT = require("dot"); // prototype pollution attack vector
Object.prototype.templateSettings = {varname:"a,b,c,d,x=console.log(25)"};
// benign looking template compilation + application
var dots = require("dot").process({path: "./resources"});
dots.mytemplate();
Then I got to thinking: doesn't this mean that virtually any JavaScript library's API options can be compromised through prototype pollution?
For example, here's express.static
used with options.
var options = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now())
}
}
app.use(express.static('public', options))
Couldn't an attacker set Object.prototype.redirect = true
, and, if unspecified by the user, a redirect would occur? And there are surely many more malicious use cases.
What can be done, as a library author, to allow passing in options but safeguard against prototype pollution?
EDIT: I'm focusing specifically on packages distributed with NPM. For example, what could the authors of doT.js do to resolve the vulnerability?