Validate and parenthesize JS in HTML templates so we don't accidentally break out of placeholders.
This commit is contained in:
parent
f5c76e6528
commit
fe12fb4a13
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ endif
|
|||||||
coffee := $(BIN)coffee -c --no-header
|
coffee := $(BIN)coffee -c --no-header
|
||||||
coffee_deps := node_modules/coffee-script/package.json
|
coffee_deps := node_modules/coffee-script/package.json
|
||||||
template := node tools/template.js
|
template := node tools/template.js
|
||||||
template_deps := package.json tools/template.js node_modules/lodash/package.json
|
template_deps := package.json tools/template.js node_modules/lodash/package.json node_modules/esprima/package.json
|
||||||
cat := node tools/cat.js
|
cat := node tools/cat.js
|
||||||
cat_deps := tools/cat.js
|
cat_deps := tools/cat.js
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"coffee-script": "1.9.3",
|
"coffee-script": "1.9.3",
|
||||||
"crx": "^3.0.3",
|
"crx": "^3.0.3",
|
||||||
|
"esprima": "^2.7.2",
|
||||||
"font-awesome": "4.5.0",
|
"font-awesome": "4.5.0",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.1",
|
||||||
"grunt-shell": "^1.2.1",
|
"grunt-shell": "^1.2.1",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var esprima = require('esprima');
|
||||||
|
|
||||||
// disable ES6 delimiters
|
// disable ES6 delimiters
|
||||||
_.templateSettings.interpolate = /<%=([\s\S]+?)%>/g;
|
_.templateSettings.interpolate = /<%=([\s\S]+?)%>/g;
|
||||||
@ -138,14 +139,23 @@ Placeholder.prototype.allowed = function(context) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Placeholder.prototype.build = function() {
|
Placeholder.prototype.build = function() {
|
||||||
// first argument is always JS expression; add backticks for embedding it in Coffeescript
|
// first argument is always JS expression; validate it so we don't accidentally break out of placeholders
|
||||||
var expr = '`'+this.args[0]+'`';
|
var expr = this.args[0];
|
||||||
|
var ast;
|
||||||
|
try {
|
||||||
|
ast = esprima.parse(expr);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Invalid JavaScript in template (${expr})`);
|
||||||
|
}
|
||||||
|
if (!(ast.type === 'Program' && ast.body.length == 1 && ast.body[0].type === 'ExpressionStatement')) {
|
||||||
|
throw new Error(`JavaScript in template is not an expression (${expr})`);
|
||||||
|
}
|
||||||
switch(this.type) {
|
switch(this.type) {
|
||||||
case '$': return `E(${expr})`; // $ : escaped text
|
case '$': return `\`E(${expr})\``; // $ : escaped text
|
||||||
case '&': return `${expr}.innerHTML`; // & : contents of HTML element or template (of form {innerHTML: "safeHTML"})
|
case '&': return `\`(${expr}).innerHTML\``; // & : contents of HTML element or template (of form {innerHTML: "safeHTML"})
|
||||||
case '@': return `E.cat(${expr})`; // @ : contents of array of HTML elements or templates (see src/General/Globals.coffee for E.cat)
|
case '@': return `\`E.cat(${expr})\``; // @ : contents of array of HTML elements or templates (see src/General/Globals.coffee for E.cat)
|
||||||
case '?':
|
case '?':
|
||||||
return `(if ${expr} then ${this.args[1] || '""'} else ${this.args[2] || '""'})`; // ? : conditional expression
|
return `(if \`(${expr})\` then ${this.args[1] || '""'} else ${this.args[2] || '""'})`; // ? : conditional expression
|
||||||
}
|
}
|
||||||
throw new Error(`Unrecognized placeholder type (${this.type})`);
|
throw new Error(`Unrecognized placeholder type (${this.type})`);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user