diff --git a/core/client/tpl/list-item.hbs b/core/client/tpl/list-item.hbs index ae4b22dbb5..78506151f4 100644 --- a/core/client/tpl/list-item.hbs +++ b/core/client/tpl/list-item.hbs @@ -1,5 +1,5 @@ -

{{title}}

+

{{{title}}}

\ No newline at end of file diff --git a/core/server/models/base.js b/core/server/models/base.js index a8e2cd1638..65db8cae4b 100644 --- a/core/server/models/base.js +++ b/core/server/models/base.js @@ -5,7 +5,8 @@ var GhostBookshelf, _ = require('underscore'), uuid = require('node-uuid'), 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 // others' if they're using the library outside of ghost. @@ -78,6 +79,10 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({ return attrs; }, + sanitize: function (attr) { + return sanitize(this.get(attr)).xss(); + }, + // #### generateSlug // Create a string act as the permalink for an object. generateSlug: function (Model, base) { diff --git a/core/server/models/post.js b/core/server/models/post.js index a25e1a4b97..111c32fff9 100644 --- a/core/server/models/post.js +++ b/core/server/models/post.js @@ -51,7 +51,7 @@ Post = GhostBookshelf.Model.extend({ 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.get('published_at')) { diff --git a/core/server/models/settings.js b/core/server/models/settings.js index ba8d299aca..cce389311d 100644 --- a/core/server/models/settings.js +++ b/core/server/models/settings.js @@ -80,7 +80,7 @@ Settings = GhostBookshelf.Model.extend({ // All blog setting keys that need their values to be escaped. 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); diff --git a/core/server/models/user.js b/core/server/models/user.js index 2e41e10203..d814a91dea 100644 --- a/core/server/models/user.js +++ b/core/server/models/user.js @@ -57,7 +57,11 @@ User = GhostBookshelf.Model.extend({ 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); }, diff --git a/core/test/unit/api_posts_spec.js b/core/test/unit/api_posts_spec.js index 48e3b56301..9355ec7f72 100644 --- a/core/test/unit/api_posts_spec.js +++ b/core/test/unit/api_posts_spec.js @@ -368,12 +368,12 @@ describe('Post Model', function () { }).then(null, done); }); - it('should escape the title', function (done) { + it('should santize the title', function (done) { - new PostModel().fetch().then(function(model) { - return model.set({'title': ''}).save(); - }).then(function(saved) { - saved.get('title').should.eql('<script>alert("hello world")</script>'); + new PostModel().fetch().then(function (model) { + return model.set({'title': ""}).save(); + }).then(function (saved) { + saved.get('title').should.eql("</title></head><body>[removed]alert('blogtitle');[removed]"); done(); }).otherwise(done);