mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Swapping escape to sanitze
issue #938 - rather than using escape, use node-validatiors santize function which is designed for preventing xss vectors - added listener for changes to both editor and settings page - added more sanitization to the user model - consistently use triple-braces when outputting blog post titles
This commit is contained in:
parent
c9235ccb0b
commit
95f9fce3be
9 changed files with 41 additions and 17 deletions
|
@ -1,5 +1,5 @@
|
||||||
<a class="permalink{{#if featured}} featured{{/if}}" href="#">
|
<a class="permalink{{#if featured}} featured{{/if}}" href="#">
|
||||||
<h3 class="entry-title">{{title}}</h3>
|
<h3 class="entry-title">{{{title}}}</h3>
|
||||||
<section class="entry-meta">
|
<section class="entry-meta">
|
||||||
<time datetime="2013-01-04" class="date">
|
<time datetime="2013-01-04" class="date">
|
||||||
{{#if published}}
|
{{#if published}}
|
||||||
|
|
|
@ -283,6 +283,8 @@
|
||||||
this.$('#entry-title').val(this.model.get('title')).focus();
|
this.$('#entry-title').val(this.model.get('title')).focus();
|
||||||
this.$('#entry-markdown').text(this.model.get('markdown'));
|
this.$('#entry-markdown').text(this.model.get('markdown'));
|
||||||
|
|
||||||
|
this.listenTo(this.model, 'change:title', this.renderTitle);
|
||||||
|
|
||||||
this.initMarkdown();
|
this.initMarkdown();
|
||||||
this.renderPreview();
|
this.renderPreview();
|
||||||
|
|
||||||
|
@ -363,6 +365,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderTitle: function () {
|
||||||
|
this.$('#entry-title').val(this.model.get('title'));
|
||||||
|
},
|
||||||
|
|
||||||
// This is a hack to remove iOS6 white space on orientation change bug
|
// This is a hack to remove iOS6 white space on orientation change bug
|
||||||
// See: http://cl.ly/RGx9
|
// See: http://cl.ly/RGx9
|
||||||
orientationChange: function () {
|
orientationChange: function () {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
this.addSubview(this.sidebar);
|
this.addSubview(this.sidebar);
|
||||||
|
|
||||||
this.listenTo(Ghost.router, "route:settings", this.changePane);
|
this.listenTo(Ghost.router, 'route:settings', this.changePane);
|
||||||
},
|
},
|
||||||
|
|
||||||
changePane: function (pane) {
|
changePane: function (pane) {
|
||||||
|
@ -155,7 +155,8 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
saveSettings: function () {
|
saveSettings: function () {
|
||||||
var title = this.$('#blog-title').val(),
|
var self = this,
|
||||||
|
title = this.$('#blog-title').val(),
|
||||||
description = this.$('#blog-description').val(),
|
description = this.$('#blog-description').val(),
|
||||||
email = this.$('#email-address').val(),
|
email = this.$('#email-address').val(),
|
||||||
postsPerPage = this.$('#postsPerPage').val();
|
postsPerPage = this.$('#postsPerPage').val();
|
||||||
|
@ -186,7 +187,7 @@
|
||||||
}, {
|
}, {
|
||||||
success: this.saveSuccess,
|
success: this.saveSuccess,
|
||||||
error: this.saveError
|
error: this.saveError
|
||||||
});
|
}).then(function () { self.render(); });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showLogo: function (e) {
|
showLogo: function (e) {
|
||||||
|
@ -212,8 +213,10 @@
|
||||||
self.model.save(data, {
|
self.model.save(data, {
|
||||||
success: self.saveSuccess,
|
success: self.saveSuccess,
|
||||||
error: self.saveError
|
error: self.saveError
|
||||||
|
}).then(function () {
|
||||||
|
self.render();
|
||||||
});
|
});
|
||||||
self.render();
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
buttonClass: "button-save right",
|
buttonClass: "button-save right",
|
||||||
|
@ -268,8 +271,9 @@
|
||||||
self.model.save(data, {
|
self.model.save(data, {
|
||||||
success: self.saveSuccess,
|
success: self.saveSuccess,
|
||||||
error: self.saveError
|
error: self.saveError
|
||||||
|
}).then(function () {
|
||||||
|
self.render();
|
||||||
});
|
});
|
||||||
self.render();
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
buttonClass: "button-save right",
|
buttonClass: "button-save right",
|
||||||
|
@ -283,7 +287,8 @@
|
||||||
|
|
||||||
|
|
||||||
saveUser: function () {
|
saveUser: function () {
|
||||||
var userName = this.$('#user-name').val(),
|
var self = this,
|
||||||
|
userName = this.$('#user-name').val(),
|
||||||
userEmail = this.$('#user-email').val(),
|
userEmail = this.$('#user-email').val(),
|
||||||
userLocation = this.$('#user-location').val(),
|
userLocation = this.$('#user-location').val(),
|
||||||
userWebsite = this.$('#user-website').val(),
|
userWebsite = this.$('#user-website').val(),
|
||||||
|
@ -322,6 +327,8 @@
|
||||||
}, {
|
}, {
|
||||||
success: this.saveSuccess,
|
success: this.saveSuccess,
|
||||||
error: this.saveError
|
error: this.saveError
|
||||||
|
}).then(function () {
|
||||||
|
self.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -365,6 +372,8 @@
|
||||||
status: 'passive'
|
status: 'passive'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}).then(function () {
|
||||||
|
self.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<nav id="site-navigation" role="navigation">
|
<nav id="site-navigation" role="navigation">
|
||||||
<ul>
|
<ul>
|
||||||
{{#links}}
|
{{#links}}
|
||||||
<li class="{{#active}}current-menu-item{{/active}}"><a title="{{title}}" href="{{url}}">{{title}}</a></li>
|
<li class="{{#active}}current-menu-item{{/active}}"><a title="{{{title}}}" href="{{url}}">{{{title}}}</a></li>
|
||||||
{{/links}}
|
{{/links}}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
|
@ -5,7 +5,8 @@ var GhostBookshelf,
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
config = require('../../../config'),
|
config = require('../../../config'),
|
||||||
Validator = require('validator').Validator;
|
Validator = require('validator').Validator,
|
||||||
|
sanitize = require('validator').sanitize;
|
||||||
|
|
||||||
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
|
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
|
||||||
// others' if they're using the library outside of ghost.
|
// others' if they're using the library outside of ghost.
|
||||||
|
@ -78,6 +79,10 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({
|
||||||
return attrs;
|
return attrs;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
sanitize: function (attr) {
|
||||||
|
return sanitize(this.get(attr)).xss();
|
||||||
|
},
|
||||||
|
|
||||||
// #### generateSlug
|
// #### generateSlug
|
||||||
// Create a string act as the permalink for an object.
|
// Create a string act as the permalink for an object.
|
||||||
generateSlug: function (Model, base) {
|
generateSlug: function (Model, base) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ Post = GhostBookshelf.Model.extend({
|
||||||
|
|
||||||
this.set('html', converter.makeHtml(this.get('markdown')));
|
this.set('html', converter.makeHtml(this.get('markdown')));
|
||||||
|
|
||||||
this.set('title', this.escape('title').trim());
|
this.set('title', this.sanitize('title').trim());
|
||||||
|
|
||||||
if (this.hasChanged('status') && this.get('status') === 'published') {
|
if (this.hasChanged('status') && this.get('status') === 'published') {
|
||||||
if (!this.get('published_at')) {
|
if (!this.get('published_at')) {
|
||||||
|
|
|
@ -80,7 +80,7 @@ Settings = GhostBookshelf.Model.extend({
|
||||||
|
|
||||||
// All blog setting keys that need their values to be escaped.
|
// All blog setting keys that need their values to be escaped.
|
||||||
if (this.get('type') === 'blog' && _.contains(['title', 'description', 'email'], this.get('key'))) {
|
if (this.get('type') === 'blog' && _.contains(['title', 'description', 'email'], this.get('key'))) {
|
||||||
this.set('value', this.escape('value'));
|
this.set('value', this.sanitize('value'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GhostBookshelf.Model.prototype.saving.apply(this, arguments);
|
return GhostBookshelf.Model.prototype.saving.apply(this, arguments);
|
||||||
|
|
|
@ -57,7 +57,11 @@ User = GhostBookshelf.Model.extend({
|
||||||
|
|
||||||
saving: function () {
|
saving: function () {
|
||||||
|
|
||||||
this.set('name', this.escape('name'));
|
this.set('name', this.sanitize('name'));
|
||||||
|
this.set('email', this.sanitize('email'));
|
||||||
|
this.set('location', this.sanitize('location'));
|
||||||
|
this.set('website', this.sanitize('website'));
|
||||||
|
this.set('bio', this.sanitize('bio'));
|
||||||
|
|
||||||
return GhostBookshelf.Model.prototype.saving.apply(this, arguments);
|
return GhostBookshelf.Model.prototype.saving.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
|
@ -368,12 +368,12 @@ describe('Post Model', function () {
|
||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should escape the title', function (done) {
|
it('should santize the title', function (done) {
|
||||||
|
|
||||||
new PostModel().fetch().then(function(model) {
|
new PostModel().fetch().then(function (model) {
|
||||||
return model.set({'title': '<script>alert("hello world")</script>'}).save();
|
return model.set({'title': "</title></head><body><script>alert('blogtitle');</script>"}).save();
|
||||||
}).then(function(saved) {
|
}).then(function (saved) {
|
||||||
saved.get('title').should.eql('<script>alert("hello world")</script>');
|
saved.get('title').should.eql("</title></head><body>[removed]alert('blogtitle');[removed]");
|
||||||
done();
|
done();
|
||||||
}).otherwise(done);
|
}).otherwise(done);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue