56 lines
2.3 KiB
JavaScript
56 lines
2.3 KiB
JavaScript
var XSSLint = require("xsslint");
|
|
var Linter = require("xsslint/linter");
|
|
var globby = require("gglobby").default;
|
|
var fs = require("fs");
|
|
|
|
XSSLint.configure({
|
|
"xssable.receiver.whitelist": ["formData"],
|
|
"jqueryObject.identifier": [/^\$/],
|
|
"jqueryObject.property": [/^\$/],
|
|
"safeString.identifier": [/(_html|Html|View|Template)$/, "html", "id"],
|
|
"safeString.function": ["h", "htmlEscape", "template", /(Template|View|Dialog)$/],
|
|
"safeString.property": ["template", "id", "height", "width", /_id$/],
|
|
"safeString.method": ["$.raw", "template", /(Template|Html)$/, "toISOString", "friendlyDatetime", /^(date|(date)?time)String$/]
|
|
});
|
|
|
|
// treat I18n.t calls w/ wrappers as html-safe, since they are
|
|
var origIsSafeString = Linter.prototype.isSafeString;
|
|
Linter.prototype.isSafeString = function(node) {
|
|
var result = origIsSafeString.call(this, node);
|
|
if (result) return result;
|
|
|
|
if (node.type !== "CallExpression") return false;
|
|
var callee = node.callee;
|
|
if (callee.type !== "MemberExpression") return false;
|
|
if (callee.object.type !== "Identifier" || callee.object.name !== "I18n") return false;
|
|
if (callee.property.type !== "Identifier" || callee.property.name !== "t" && callee.property.name !== "translate") return false;
|
|
var lastArg = node.arguments[node.arguments.length - 1];
|
|
if (lastArg.type !== "ObjectExpression") return false;
|
|
var wrapperOption = lastArg.properties.filter(function(prop){
|
|
return prop.key.name === "wrapper" || prop.key.name === "wrappers";
|
|
});
|
|
return (wrapperOption.length > 0)
|
|
}
|
|
|
|
process.chdir("public/javascripts");
|
|
var ignores = fs.readFileSync(".xssignore").toString().trim().split(/\r?\n|\r/);
|
|
var files = globby.select(["*.js"]).reject(ignores).files;
|
|
var warningCount = 0;
|
|
|
|
console.log("Checking for potential XSS vulnerabilities...");
|
|
files.forEach(function(file) {
|
|
var warnings = XSSLint.run(file);
|
|
warningCount += warnings.length;
|
|
for (var i = 0, len = warnings.length; i < len; i++) {
|
|
var warning = warnings[i];
|
|
console.error(file + ":" + warning.line + ": possibly XSS-able " + (warning.method == "+" ? "HTML string concatenation" : "argument to `" + warning.method + "`"));
|
|
}
|
|
});
|
|
|
|
if (warningCount) {
|
|
console.error("\033[31mFound " + warningCount + " potential vulnerabilities\033[0m");
|
|
process.exit(1)
|
|
} else {
|
|
console.log("No problems found!")
|
|
}
|