This repository has been archived by the owner on Sep 5, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
decoupled from depending on exphbs.compileTemplate #2
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,68 +9,22 @@ Authors: Nera Liu <[email protected]> | |
*/ | ||
/*jshint -W030 */ | ||
var util = require("util"), | ||
debug = require('debug')('esh'), | ||
expressHandlebars = require('express-handlebars').ExpressHandlebars, | ||
xssFilters = require('xss-filters'), | ||
privateFilters = xssFilters._privFilters, | ||
ContextParserHandlebars = require("context-parser-handlebars"); | ||
secureHandlebars = require('./secure-handlebars'); | ||
|
||
function ExpressSecureHandlebars(config) { | ||
|
||
// override the original handlebars with secure-handlebars | ||
config || (config = {}); | ||
config.handlebars = config.secureHandlebars || secureHandlebars; | ||
|
||
/* calling super constructor */ | ||
this.constructor.super_.call(this, config); | ||
|
||
if (this.handlebars.helpers) { | ||
var h = this.handlebars; | ||
// register below the filters that are automatically applied by context parser | ||
[ | ||
'y', | ||
'yd', 'yc', | ||
'yavd', 'yavs', 'yavu', | ||
'yu', 'yuc', | ||
'yubl', 'yufull' | ||
].forEach(function(filterName){ | ||
h.registerHelper(filterName, privateFilters[filterName]); | ||
}); | ||
// register below the filters that might be manually applied by developers | ||
[ | ||
'inHTMLData', 'inHTMLComment', | ||
'inSingleQuotedAttr', 'inDoubleQuotedAttr', 'inUnQuotedAttr', | ||
'uriInSingleQuotedAttr', 'uriInDoubleQuotedAttr', 'uriInUnQuotedAttr', 'uriInHTMLData', 'uriInHTMLComment', | ||
'uriPathInSingleQuotedAttr', 'uriPathInDoubleQuotedAttr', 'uriPathInUnQuotedAttr', 'uriPathInHTMLData', 'uriPathInHTMLComment', | ||
'uriQueryInSingleQuotedAttr', 'uriQueryInDoubleQuotedAttr', 'uriQueryInUnQuotedAttr', 'uriQueryInHTMLData', 'uriQueryInHTMLComment', | ||
'uriComponentInSingleQuotedAttr', 'uriComponentInDoubleQuotedAttr', 'uriComponentInUnQuotedAttr', 'uriComponentInHTMLData', 'uriComponentInHTMLComment', | ||
'uriFragmentInSingleQuotedAttr', 'uriFragmentInDoubleQuotedAttr', 'uriFragmentInUnQuotedAttr', 'uriFragmentInHTMLData', 'uriFragmentInHTMLComment' | ||
].forEach(function(filterName){ | ||
h.registerHelper(filterName, xssFilters[filterName]); | ||
}); | ||
debug(h.helpers); | ||
} | ||
} | ||
|
||
/* inheriting the express-handlebars */ | ||
util.inherits(ExpressSecureHandlebars, expressHandlebars); | ||
|
||
ExpressSecureHandlebars.prototype.compileTemplate = function (template, options) { | ||
if (!options || !options.precompiled) { | ||
try { | ||
var parser = new ContextParserHandlebars({printCharEnable: false}); | ||
parser.contextualize(template); | ||
template = parser.getOutput(); | ||
} catch (err) { | ||
console.log('====================='); | ||
console.log("[WARNING] ExpressSecureHandlebars: falling back to the original express-handlebars"); | ||
Object.keys(err).forEach(function(k){console.log(k.toUpperCase() + ':\n' + err[k]);}); | ||
console.log("TEMPLATE:\n" + template); | ||
console.log('====================='); | ||
} | ||
} else { | ||
console.log("[WARNING] ExpressSecureHandlebars: ContextParserHandlebars cannot handle precompiled template!"); | ||
} | ||
|
||
return ExpressSecureHandlebars.super_.prototype.compileTemplate.call(this, template, options); | ||
}; | ||
|
||
/* exporting the same signature of express-handlebars */ | ||
exports = module.exports = exphbs; | ||
exports.create = create; | ||
|
@@ -84,4 +38,4 @@ function exphbs(config) { | |
|
||
function create(config) { | ||
return new ExpressSecureHandlebars(config); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
Copyright (c) 2015, Yahoo Inc. All rights reserved. | ||
Copyrights licensed under the New BSD License. | ||
See the accompanying LICENSE file for terms. | ||
|
||
Authors: Nera Liu <[email protected]> | ||
Albert Yu <[email protected]> | ||
Adonis Fung <[email protected]> | ||
*/ | ||
/*jshint -W030 */ | ||
var Handlebars = require('handlebars'), | ||
ContextParserHandlebars = require("context-parser-handlebars"), | ||
xssFilters = require('xss-filters'); | ||
|
||
|
||
|
||
function preprocess(template) { | ||
try { | ||
if (template) { | ||
var parser = new ContextParserHandlebars({printCharEnable: false}); | ||
parser.contextualize(template); | ||
return parser.getOutput(); | ||
} | ||
} catch (err) { | ||
console.log('====================='); | ||
console.log("[WARNING] SecureHandlebars: falling back to the original template"); | ||
Object.keys(err).forEach(function(k){console.log(k.toUpperCase() + ':\n' + err[k]);}); | ||
console.log("TEMPLATE:\n" + template); | ||
console.log('====================='); | ||
} | ||
return template; | ||
} | ||
|
||
function override(h) { | ||
var c = h.compile, | ||
pc = h.precompile, | ||
privateFilters = xssFilters._privFilters; | ||
|
||
// override precompile function to preprocess the template first | ||
h.precompile = function (template, options) { | ||
return pc.call(this, preprocess(template), options); | ||
}; | ||
|
||
// override compile function to preprocess the template first | ||
h.compile = function (template, options) { | ||
return c.call(this, preprocess(template), options); | ||
}; | ||
|
||
// register below the filters that are automatically applied by context parser | ||
[ | ||
'y', | ||
'yd', 'yc', | ||
'yavd', 'yavs', 'yavu', | ||
'yu', 'yuc', | ||
'yubl', 'yufull' | ||
].forEach(function(filterName){ | ||
h.registerHelper(filterName, privateFilters[filterName]); | ||
}); | ||
|
||
// register below the filters that might be manually applied by developers | ||
[ | ||
'inHTMLData', 'inHTMLComment', | ||
'inSingleQuotedAttr', 'inDoubleQuotedAttr', 'inUnQuotedAttr', | ||
'uriInSingleQuotedAttr', 'uriInDoubleQuotedAttr', 'uriInUnQuotedAttr', 'uriInHTMLData', 'uriInHTMLComment', | ||
'uriPathInSingleQuotedAttr', 'uriPathInDoubleQuotedAttr', 'uriPathInUnQuotedAttr', 'uriPathInHTMLData', 'uriPathInHTMLComment', | ||
'uriQueryInSingleQuotedAttr', 'uriQueryInDoubleQuotedAttr', 'uriQueryInUnQuotedAttr', 'uriQueryInHTMLData', 'uriQueryInHTMLComment', | ||
'uriComponentInSingleQuotedAttr', 'uriComponentInDoubleQuotedAttr', 'uriComponentInUnQuotedAttr', 'uriComponentInHTMLData', 'uriComponentInHTMLComment', | ||
'uriFragmentInSingleQuotedAttr', 'uriFragmentInDoubleQuotedAttr', 'uriFragmentInUnQuotedAttr', 'uriFragmentInHTMLData', 'uriFragmentInHTMLComment' | ||
].forEach(function(filterName){ | ||
h.registerHelper(filterName, xssFilters[filterName]); | ||
}); | ||
return h; | ||
} | ||
|
||
|
||
if (module && module.exports) { | ||
module.exports = override(Handlebars.create()); | ||
} else { | ||
override(Handlebars); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,18 +12,18 @@ Authors: Nera Liu <[email protected]> | |
require("mocha"); | ||
var expect = require('expect.js'), | ||
expressHandlebars = require('express-handlebars'), | ||
expressSecureHandlebars = require('../../src/express-secure-handlebars.js'); | ||
expressSecureHandlebars = require('../../src/express-secure-handlebars.js'), | ||
handlebars = require('handlebars'); | ||
|
||
describe("Express Secure Handlebars test suite", function() { | ||
|
||
it("Express Secure Handlebars same signature test", function() { | ||
it("same signature test", function() { | ||
// console.log(expressHandlebars); | ||
expect(typeof expressHandlebars).to.be.equal('function'); | ||
expect(typeof expressHandlebars.create).to.be.equal('function'); | ||
expect(typeof expressHandlebars.ExpressHandlebars).to.be.equal('function'); | ||
expect(expressHandlebars.create).to.be.ok(); | ||
expect(expressHandlebars.ExpressHandlebars).to.be.ok(); | ||
expect(expressHandlebars.create().compileTemplate).to.be.ok(); | ||
|
||
|
||
// console.log(expressSecureHandlebars); | ||
|
@@ -32,41 +32,50 @@ Authors: Nera Liu <[email protected]> | |
expect(typeof expressSecureHandlebars.ExpressHandlebars).to.be.equal('function'); | ||
expect(expressSecureHandlebars.create).to.be.ok(); | ||
expect(expressSecureHandlebars.ExpressHandlebars).to.be.ok(); | ||
expect(expressSecureHandlebars.create().compileTemplate).to.be.ok(); | ||
}); | ||
|
||
it("Express Secure Handlebars new instance test", function() { | ||
it("new instance test", function() { | ||
var expHbs = new expressHandlebars(); | ||
expect(typeof expHbs).to.be.equal('function'); | ||
var expSecureHbs = new expressSecureHandlebars(); | ||
expect(typeof expSecureHbs).to.be.equal('function'); | ||
}); | ||
|
||
it("Express Secure Handlebars create() new instance with handlebars test", function() { | ||
it("create() new instance with handlebars test", function() { | ||
var expHbs = expressHandlebars.create(); | ||
expect(expHbs.handlebars).to.be.ok(); | ||
var expSecureHbs = expressSecureHandlebars.create(); | ||
expect(expSecureHbs.handlebars).to.be.ok(); | ||
}); | ||
|
||
var data = {url: 'javascript:alert(1)'}; | ||
it("Express Secure Handlebars fallback on error test", function() { | ||
var template = '{{#if url}}<a href="{{url}}"{{else}}<a href="{{url}}">closed</a>{{/if}}'; | ||
var expSecureHbs = expressSecureHandlebars.create(); | ||
var t1 = expSecureHbs.compileTemplate(template); | ||
|
||
var expHbs = expressHandlebars.create(); | ||
var t2 = expHbs.compileTemplate(template); | ||
it("empty template test", function() { | ||
expect(new expressSecureHandlebars.create().handlebars.compile('')(data)).to.be.equal(''); | ||
}); | ||
|
||
var template = '{{#if url}}<a href="{{url}}"{{else}}<a href="{{url}}">closed</a>{{/if}}'; | ||
it("handlebars fallback on compile error test", function() { | ||
var t1 = expressSecureHandlebars.create().handlebars.compile(template); | ||
var t2 = expressHandlebars.create().handlebars.compile(template); | ||
|
||
expect(t1(data)).to.be.equal(t2(data)); | ||
}); | ||
|
||
it("Express Secure Handlebars compileTemplate test", function() { | ||
it("handlebars fallback on precompile error test", function() { | ||
var templateSpec1 = expressSecureHandlebars.create().handlebars.precompile(template); | ||
var templateSpec2 = expressHandlebars.create().handlebars.precompile(template); | ||
var t1 = handlebars.template(eval('(' + templateSpec1 + ')')); | ||
var t2 = handlebars.template(eval('(' + templateSpec2 + ')')); | ||
|
||
expect(t1(data)).to.be.equal(t2(data)); | ||
}); | ||
|
||
it("handlebars compile test", function() { | ||
var template = '<a href="{{url}}">closed</a>'; | ||
var expSecureHbs = expressSecureHandlebars.create(); | ||
var t1 = expSecureHbs.compileTemplate(template); | ||
var t1 = expressSecureHandlebars.create().handlebars.compile(template); | ||
var t2 = expressHandlebars.create().handlebars.compile(template); | ||
|
||
var expHbs = expressHandlebars.create(); | ||
var t2 = expHbs.compileTemplate(template); | ||
expect(t1(data)).not.to.be.equal(t2(data)); | ||
}); | ||
}); | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good! we can simply create the secure-handlebars and replace this line later.