express-sanitize-escape
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -14,3 +14,2 @@ /*! | ||
/** | ||
@@ -26,54 +25,77 @@ * Simple middleware that wraps sanitzer and can be exposed | ||
*/ | ||
exports.middleware = function expressSanitized() { | ||
module.exports = { | ||
return function expressSanitized(req, res, next) { | ||
encoder: 'htmlEncode', | ||
[req.body, req.query].forEach(function (val, ipar, request) { | ||
if (_.size(val)) { | ||
request[ipar] = sanitize(request[ipar]) | ||
sanitize: true, | ||
_sanitize: function(obj) { | ||
var self = this; | ||
if (typeof obj === 'string') { | ||
if (self.sanitize) | ||
{ | ||
obj = sanitizer.sanitize(obj); | ||
} | ||
}); | ||
if (self.encoder) | ||
{ | ||
obj = htmlencode[self.encoder](obj); | ||
} | ||
return obj; | ||
} | ||
if (obj instanceof Object) { | ||
Object.keys(obj).forEach(function(prop) { | ||
obj[prop] = self._sanitize(obj[prop]); | ||
}); | ||
return obj; | ||
} | ||
return obj; | ||
}, | ||
next(); | ||
} | ||
middleware: function(options) { | ||
var self = this; | ||
if (options && (_.includes(_.keys(htmlencode), options.encoder) || typeof(options.encoder) === 'boolean')) { | ||
self.encoder = options.encoder; | ||
} | ||
if (options && typeof(options.sanitize) === 'boolean') { | ||
self.sanitize = options.sanitize; | ||
} | ||
return function expressSanitized(req, res, next) { | ||
}; | ||
[req.body, req.query].forEach(function (val, ipar, request) { | ||
if (_.size(val)) { | ||
request[ipar] = self._sanitize(request[ipar], options) | ||
} | ||
}); | ||
exports.sanitizeParams = function(router, paramNames) | ||
{ | ||
paramNames.forEach(function(paramName) | ||
{ | ||
router.param(paramName, function(req, res, next) | ||
{ | ||
req.params[paramName] = sanitize(req.params[paramName]); | ||
next(); | ||
}); | ||
}); | ||
}; | ||
} | ||
}, | ||
function sanitize(obj) { | ||
if (typeof obj === 'string') { | ||
return htmlencode.htmlEncode(sanitizer.sanitize(obj)); | ||
} | ||
if (obj instanceof Object) { | ||
Object.keys(obj).forEach(function(prop) { | ||
obj[prop] = sanitize(obj[prop]); | ||
sanitizeParams: function(router, paramNames, options) { | ||
var self = this; | ||
if (options && _.includes(_.keys(htmlencode), options.encoder)) { | ||
this.encoder = htmlencode[options.encoder]; | ||
} | ||
paramNames.forEach(function (paramName) { | ||
router.param(paramName, function (req, res, next) { | ||
req.params[paramName] = self._sanitize(req.params[paramName]); | ||
next(); | ||
}); | ||
}); | ||
return obj; | ||
} | ||
return obj; | ||
} | ||
}, | ||
exports.htmlDecodeBody = function htmlDecodeBody(obj) { | ||
if (typeof obj === 'string') { | ||
return htmlencode.htmlDecode(sanitizer.sanitize(obj)); | ||
} | ||
if (obj instanceof Object) { | ||
Object.keys(obj).forEach(function(prop) { | ||
obj[prop] = exports.htmlDecodeBody(obj[prop]); | ||
}); | ||
htmlDecodeBody: function htmlDecodeBody(obj) { | ||
var self = this; | ||
if (typeof obj === 'string') { | ||
return htmlencode.htmlDecode(sanitizer.sanitize(obj)); | ||
} | ||
if (obj instanceof Object) { | ||
Object.keys(obj).forEach(function (prop) { | ||
obj[prop] = self.htmlDecodeBody(obj[prop]); | ||
}); | ||
return obj; | ||
} | ||
return obj; | ||
} | ||
return obj; | ||
}; |
{ | ||
"name": "express-sanitize-escape", | ||
"description": "Express middleware for the sanitizer module using Caja's HTML Sanitizer and HTML escape using htmlencode.", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"author": "Justin Hamade <justin@fingerfoodstudios.com>", | ||
@@ -6,0 +6,0 @@ "homepage": "https://github.com/fingerfoodstudios/express-sanitize-esacpe", |
@@ -9,21 +9,62 @@ /** | ||
var express = require('express'); | ||
var htmlencode = require('htmlencode'); | ||
var request = require('supertest'); | ||
var should = require('chai').should(); | ||
var sanitizer = require('sanitizer'); | ||
var expressSanitized = require('./../lib/express-sanitize-escape'); | ||
var app = express(); | ||
app.use(bodyParser.json()); | ||
app.use(expressSanitized.middleware()); // this line follows express.bodyParser() | ||
describe('POST /test encoder: false sanitize: true', function () { | ||
encoderTest(false, true); | ||
}); | ||
app.post('/test', function(req, res){ | ||
res.status(200).json(req.body); | ||
describe('POST /test encoder: false sanitize: false', function () { | ||
encoderTest(false, false); | ||
}); | ||
describe('POST /test', function(){ | ||
describe('POST /test encoder: XSSEncode sanitize: true', function () { | ||
encoderTest('XSSEncode', true); | ||
}); | ||
it('respond with html tags removed', function(done) { | ||
describe('POST /test encoder: XSSEncode sanitize: false', function () { | ||
encoderTest('XSSEncode', false); | ||
}); | ||
describe('POST /test encoder: htmlEncode sanitize: true', function () { | ||
encoderTest('htmlEncode', true); | ||
}); | ||
describe('POST /test encoder: htmlEncode sanitize: false', function () { | ||
encoderTest('htmlEncode', false); | ||
}); | ||
function encoderTest(encoder, sanitize) { | ||
var entities = '< > \' " & ä 汉语 éöîõæœÉÖßÉéÈèÊêËëÇçÀàÂâÆæÔôŒœÙùÛûÜüŸÿ'; | ||
var hasHtml = '<script>document.write(\'cookie monster\')</script> download now'; | ||
var hasHtmlEncoded = hasHtml; | ||
var entitiesEncoded = entities; | ||
var app = express(); | ||
before(function(done) | ||
{ | ||
if (sanitize) { | ||
entitiesEncoded = sanitizer.sanitize(entitiesEncoded); | ||
hasHtmlEncoded = sanitizer.sanitize(hasHtmlEncoded); | ||
} | ||
if (encoder) { | ||
entitiesEncoded = htmlencode[encoder](entitiesEncoded); | ||
hasHtmlEncoded = htmlencode[encoder](hasHtmlEncoded); | ||
} | ||
app.use(bodyParser.json()); | ||
app.use(expressSanitized.middleware({encoder: encoder, sanitize: sanitize})); // this line follows express.bodyParser() | ||
app.post('/test', function (req, res) { | ||
res.status(200).json(req.body); | ||
}); | ||
done(); | ||
}); | ||
it('respond with html tags removed', function (done) { | ||
request(app) | ||
.post('/test') | ||
.send({hasHtml: '<script>document.write(\'cookie monster\')</script> download now'}) | ||
.send({hasHtml: hasHtml}) | ||
.expect('Content-Type', /json/) | ||
@@ -34,3 +75,3 @@ .expect(200) | ||
try { | ||
res.body.should.have.property('hasHtml', ' download now'); | ||
res.body.should.have.property('hasHtml', hasHtmlEncoded); | ||
done(); | ||
@@ -43,6 +84,6 @@ } catch (err) { | ||
it('respond with html entities escaped', function(done) { | ||
it('respond with html entities escaped', function (done) { | ||
request(app) | ||
.post('/test') | ||
.send({hasHtmlEntities: '< > \' " & ä 汉语'}) | ||
.send({hasHtmlEntities: entities}) | ||
.expect('Content-Type', /json/) | ||
@@ -53,4 +94,4 @@ .expect(200) | ||
try { | ||
res.body.should.have.property('hasHtmlEntities', '< > ' " & ä 汉语'); | ||
expressSanitized.htmlDecodeBody(res.body).should.have.property('hasHtmlEntities', '< > \' " & ä 汉语'); | ||
res.body.should.have.property('hasHtmlEntities', entitiesEncoded); | ||
expressSanitized.htmlDecodeBody(res.body).should.have.property('hasHtmlEntities', entities); | ||
done(); | ||
@@ -62,11 +103,11 @@ } catch (err) { | ||
}); | ||
it('respond with arrays number and strings', function(done) { | ||
it('respond with arrays number and strings', function (done) { | ||
var testJson = { | ||
first: '<script>document.write(\'cookie monster\')</script> download now', | ||
first: hasHtml, | ||
secondObj: { | ||
third: '< > \' " &' | ||
third: entities | ||
}, | ||
fourthArray: [ | ||
'<pre>remove</pre> this string', | ||
hasHtml, | ||
100, | ||
@@ -76,3 +117,3 @@ true | ||
}; | ||
request(app) | ||
@@ -86,4 +127,5 @@ .post('/test') | ||
try { | ||
res.body.should.have.deep.property('secondObj.third', '< > ' " &'); | ||
res.body.fourthArray[0].should.equal('<pre>remove</pre> this string'); | ||
res.body.should.have.property('first', hasHtmlEncoded); | ||
res.body.should.have.deep.property('secondObj.third', entitiesEncoded); | ||
res.body.fourthArray[0].should.equal(hasHtmlEncoded); | ||
done(); | ||
@@ -95,2 +137,2 @@ } catch (err) { | ||
}); | ||
}); | ||
} |
12511
202