fix(xss): Update site to use remarkable instead of marked

https://snyk.io/vuln/npm%3Amarked%3A20150520
https://github.com/chjj/marked/pull/592
This commit is contained in:
Sabe Jones
2016-04-21 15:46:48 +00:00
committed by Blade Barringer
parent 43f8e943f6
commit 867146dc19
8 changed files with 65 additions and 66 deletions

View File

@@ -37,7 +37,7 @@
"jquery-ui": "1.10.3", "jquery-ui": "1.10.3",
"jquery.cookie": "1.4.0", "jquery.cookie": "1.4.0",
"js-emoji": "snicker/js-emoji#f25d8a303f", "js-emoji": "snicker/js-emoji#f25d8a303f",
"marked": "0.2.9", "remarkable": "^1.6.2",
"ngInfiniteScroll": "1.0.0", "ngInfiniteScroll": "1.0.0",
"pnotify": "1.3.1", "pnotify": "1.3.1",
"sticky": "*", "sticky": "*",

View File

@@ -6,18 +6,10 @@
*/ */
(function(){ (function(){
var md = function () { var md = function () {
marked.setOptions({ var remarkable = new Remarkable({
gfm:true, // TODO: Add in code highlighting?
pedantic:false, // highlight: function (#<{(|str, lang|)}>#) { return ''; }
sanitize:true linkify: true
// callback for code highlighter
// Uncomment this (and htljs.tabReplace below) if we add in highlight.js (http://www.heikura.me/#!/angularjs-markdown-directive)
// highlight:function (code, lang) {
// if (lang != undefined)
// return hljs.highlight(lang, code).value;
//
// return hljs.highlightAuto(code).value;
// }
}); });
emoji.img_path = 'common/img/emoji/unicode/'; emoji.img_path = 'common/img/emoji/unicode/';
@@ -26,57 +18,60 @@
if (markdown == undefined) if (markdown == undefined)
return ''; return '';
markdown = marked(markdown); markdown = remarkable.render(markdown);
markdown = emoji.replace_colons(markdown); markdown = emoji.replace_colons(markdown);
markdown = emoji.replace_unified(markdown); markdown = emoji.replace_unified(markdown);
return markdown; return markdown;
}; };
// This was applie to marked, the old markdown library which has an xss exploit.
// If we want this behavior again, we'll need to rewrite it.
// ---
// [nickgordon20131123] this hacky override wraps images with a link to the image in a new window, and also adds some classes in case we want to style // [nickgordon20131123] this hacky override wraps images with a link to the image in a new window, and also adds some classes in case we want to style
marked.InlineLexer.prototype.outputLink = function(cap, link) { // marked.InlineLexer.prototype.outputLink = function(cap, link) {
var escape = function(html, encode) { // var escape = function(html, encode) {
return html // return html
.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;') // .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
.replace(/</g, '&lt;') // .replace(/</g, '&lt;')
.replace(/>/g, '&gt;') // .replace(/>/g, '&gt;')
.replace(/"/g, '&quot;') // .replace(/"/g, '&quot;')
.replace(/'/g, '&#39;'); // .replace(/'/g, '&#39;');
}; // };
if (cap[0].charAt(0) !== '!') { // if (cap[0].charAt(0) !== '!') {
return '<a class="markdown-link" target="_blank" href="' // return '<a class="markdown-link" target="_blank" href="'
+ escape(link.href) // + escape(link.href)
+ '"' // + '"'
+ (link.title // + (link.title
? ' title="' // ? ' title="'
+ escape(link.title) // + escape(link.title)
+ '"' // + '"'
: '') // : '')
+ '>' // + '>'
+ this.output(cap[1]) // + this.output(cap[1])
+ '</a>'; // + '</a>';
} else { // } else {
return '<a class="markdown-img-link" target="_blank" href="' // return '<a class="markdown-img-link" target="_blank" href="'
+ escape(link.href) // + escape(link.href)
+ '"' // + '"'
+ (link.title // + (link.title
? ' title="' // ? ' title="'
+ escape(link.title) // + escape(link.title)
+ '"' // + '"'
: '') // : '')
+ '><img class="markdown-img" src="' // + '><img class="markdown-img" src="'
+ escape(link.href) // + escape(link.href)
+ '" alt="' // + '" alt="'
+ escape(cap[1]) // + escape(cap[1])
+ '"' // + '"'
+ (link.title // + (link.title
? ' title="' // ? ' title="'
+ escape(link.title) // + escape(link.title)
+ '"' // + '"'
: '') // : '')
+ '></a>'; // + '></a>';
} // }
} // }
//hljs.tabReplace = ' '; //hljs.tabReplace = ' ';

View File

@@ -31,7 +31,7 @@ module.exports = function karmaConfig (config) {
'website/public/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js', 'website/public/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
'website/public/bower_components/select2/select2.js', 'website/public/bower_components/select2/select2.js',
'website/public/bower_components/angular-ui-select2/src/select2.js', 'website/public/bower_components/angular-ui-select2/src/select2.js',
'website/public/bower_components/marked/lib/marked.js', 'website/public/bower_components/remarkable/dist/remarkable.min.js',
'website/public/bower_components/js-emoji/emoji.js', 'website/public/bower_components/js-emoji/emoji.js',
'common/dist/scripts/habitrpg-shared.js', 'common/dist/scripts/habitrpg-shared.js',

View File

@@ -52,7 +52,6 @@
"js2xmlparser": "~1.0.0", "js2xmlparser": "~1.0.0",
"lodash": "^3.10.1", "lodash": "^3.10.1",
"loggly": "~1.0.8", "loggly": "~1.0.8",
"marked": "^0.3.5",
"merge-stream": "^1.0.0", "merge-stream": "^1.0.0",
"method-override": "^2.3.5", "method-override": "^2.3.5",
"moment": "~2.10.6", "moment": "~2.10.6",
@@ -72,6 +71,7 @@
"ps-tree": "^1.0.0", "ps-tree": "^1.0.0",
"push-notify": "^1.1.1", "push-notify": "^1.1.1",
"q": "^1.4.1", "q": "^1.4.1",
"remarkable": "^1.6.2",
"request": "~2.44.0", "request": "~2.44.0",
"s3-upload-stream": "^1.0.6", "s3-upload-stream": "^1.0.6",
"serve-favicon": "^2.3.0", "serve-favicon": "^2.3.0",

View File

@@ -8,7 +8,7 @@
"bower_components/bootstrap-tour/build/js/bootstrap-tour.js", "bower_components/bootstrap-tour/build/js/bootstrap-tour.js",
"bower_components/angular/angular.js", "bower_components/angular/angular.js",
"bower_components/angular-sanitize/angular-sanitize.js", "bower_components/angular-sanitize/angular-sanitize.js",
"bower_components/marked/lib/marked.js", "bower_components/remarkable/dist/remarkable.min.js",
"bower_components/angular-ui-router/release/angular-ui-router.js", "bower_components/angular-ui-router/release/angular-ui-router.js",
"bower_components/angular-resource/angular-resource.min.js", "bower_components/angular-resource/angular-resource.min.js",
"bower_components/angular-ui-utils/ui-utils.min.js", "bower_components/angular-ui-utils/ui-utils.min.js",

View File

@@ -4,6 +4,10 @@ var router = express.Router();
var _ = require('lodash'); var _ = require('lodash');
var locals = require('../middlewares/locals'); var locals = require('../middlewares/locals');
var i18n = require('../libs/i18n'); var i18n = require('../libs/i18n');
var Remarkable = require('remarkable');
var md = new Remarkable({
html: true,
});
const TOTAL_USER_COUNT = '1,100,000'; const TOTAL_USER_COUNT = '1,100,000';
@@ -26,7 +30,7 @@ _.each(pages, function(name){
router.get('/static/' + name, i18n.getUserLanguage, locals, function(req, res) { router.get('/static/' + name, i18n.getUserLanguage, locals, function(req, res) {
res.render( 'static/' + name, { res.render( 'static/' + name, {
env: res.locals.habitrpg, env: res.locals.habitrpg,
marked: require('marked'), md: md,
userCount: TOTAL_USER_COUNT userCount: TOTAL_USER_COUNT
}); });
}); });
@@ -40,7 +44,7 @@ _.each(shareables, function(name){
router.get('/social/' + name, i18n.getUserLanguage, locals, function(req, res) { router.get('/social/' + name, i18n.getUserLanguage, locals, function(req, res) {
res.render( 'social/' + name, { res.render( 'social/' + name, {
env: res.locals.habitrpg, env: res.locals.habitrpg,
marked: require('marked'), md: md,
userCount: TOTAL_USER_COUNT userCount: TOTAL_USER_COUNT
}); });
}); });

View File

@@ -22,8 +22,8 @@ block content
- for heading, index in headings - for heading, index in headings
a.h2.accordion.collapsed(ng-href='#' + heading, data-toggle='collapse')=env.t('faqQuestion' + index) a.h2.accordion.collapsed(ng-href='#' + heading, data-toggle='collapse')=env.t('faqQuestion' + index)
.clearfix.collapse(id=heading) .clearfix.collapse(id=heading)
!=marked(env.t('webFaqAnswer' + index)) !=md.render(env.t('webFaqAnswer' + index))
hr hr
h3!=marked(env.t('webFaqStillNeedHelp')) h3!=md.render(env.t('webFaqStillNeedHelp'))

View File

@@ -18,6 +18,6 @@ block content
- for step in stepsNum - for step in stepsNum
h3=env.t('step'+step) h3=env.t('step'+step)
p p
!=marked(env.t('webStep'+step+'Text')) !=md.render(env.t('webStep'+step+'Text'))
hr hr
!=marked(env.t('overviewQuestions')) !=md.render(env.t('overviewQuestions'))