diff --git a/public/src/client/topic.js b/public/src/client/topic.js
index c1c58f2862..1179bdb331 100644
--- a/public/src/client/topic.js
+++ b/public/src/client/topic.js
@@ -215,10 +215,11 @@ define('forum/topic', [
 	}
 
 	function updateTopicTitle() {
+		var span = components.get('navbar/title').find('span');
 		if ($(window).scrollTop() > 50) {
-			components.get('navbar/title').find('span').text(ajaxify.data.title).show();
+			span.html(ajaxify.data.titleEscaped).show();
 		} else {
-			components.get('navbar/title').find('span').text('').hide();
+			span.html('').hide();
 		}
 		app.removeAlert('bookmark');
 	}
diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js
index cf594041b6..33199f7f0b 100644
--- a/public/src/client/topic/postTools.js
+++ b/public/src/client/topic/postTools.js
@@ -4,17 +4,14 @@
 
 define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator'], function(share, navigator, components, translator) {
 
-	var PostTools = {},
-		topicName;
+	var PostTools = {};
 
 	PostTools.init = function(tid) {
-		topicName = ajaxify.data.title;
-
 		renderMenu();
 
 		addPostHandlers(tid);
 
-		share.addShareHandlers(topicName);
+		share.addShareHandlers(ajaxify.data.title);
 
 		addVoteHandler();
 
@@ -106,15 +103,15 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 		var postContainer = components.get('topic');
 
 		postContainer.on('click', '[component="post/quote"]', function() {
-			onQuoteClicked($(this), tid, topicName);
+			onQuoteClicked($(this), tid);
 		});
 
 		postContainer.on('click', '[component="post/reply"]', function() {
-			onReplyClicked($(this), tid, topicName);
+			onReplyClicked($(this), tid);
 		});
 
 		$('.topic').on('click', '[component="topic/reply"]', function() {
-			onReplyClicked($(this), tid, topicName);
+			onReplyClicked($(this), tid);
 		});
 
 		$('.topic').on('click', '[component="topic/reply-as-topic"]', function() {
@@ -174,7 +171,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 		});
 	}
 
-	function onReplyClicked(button, tid, topicName) {
+	function onReplyClicked(button, tid) {
 		showStaleWarning(function(proceed) {
 			if (!proceed) {
 				var selectionText = '',
@@ -197,7 +194,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 						slug: ajaxify.data.slug,
 						index: getData(button, 'data-index'),
 						pid: toPid,
-						topicName: topicName,
+						topicName: ajaxify.data.title,
 						username: username,
 						text: selectionText
 					});
@@ -205,7 +202,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 					$(window).trigger('action:composer.post.new', {
 						tid: tid,
 						pid: toPid,
-						topicName: topicName,
+						topicName: ajaxify.data.title,
 						text: username ? username + ' ' : ''
 					});
 				}
@@ -213,7 +210,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 		});
 	}
 
-	function onQuoteClicked(button, tid, topicName) {
+	function onQuoteClicked(button, tid) {
 		showStaleWarning(function(proceed) {
 			if (!proceed) {
 				var username = getUserName(button),
@@ -230,7 +227,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 						index: getData(button, 'data-index'),
 						pid: pid,
 						username: username,
-						topicName: topicName,
+						topicName: ajaxify.data.title,
 						text: post
 					});
 				});
@@ -368,7 +365,7 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
 			});
 
 			topicId.on('keyup change', function() {
-				moveBtn.attr('disabled', !topicId.val())
+				moveBtn.attr('disabled', !topicId.val());
 			});
 
 			moveBtn.on('click', function() {
diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js
index 6182b4c554..e05017c767 100644
--- a/public/src/client/topic/posts.js
+++ b/public/src/client/topic/posts.js
@@ -138,12 +138,6 @@ define('forum/topic/posts', [
 			before = repliesSelector.first();
 		}
 
-		data.title = $('<div></div>').text(ajaxify.data.title).html();
-		data.slug = ajaxify.data.slug;
-		data.tags = ajaxify.data.tags;
-		data.viewcount = ajaxify.data.viewcount;
-		data.isFollowing = ajaxify.data.isFollowing;
-
 		$(window).trigger('action:posts.loading', {posts: data.posts, after: after, before: before});
 
 		app.parseAndTranslate('topic', 'posts', data, function(html) {
diff --git a/src/controllers/topics.js b/src/controllers/topics.js
index 018d1e83eb..2690943247 100644
--- a/src/controllers/topics.js
+++ b/src/controllers/topics.js
@@ -1,26 +1,29 @@
 "use strict";
 
-var topicsController = {},
-	async = require('async'),
-	S = require('string'),
-	nconf = require('nconf'),
-
-	user = require('../user'),
-	meta = require('../meta'),
-	topics = require('../topics'),
-	posts = require('../posts'),
-	privileges = require('../privileges'),
-	plugins = require('../plugins'),
-	helpers = require('./helpers'),
-	pagination = require('../pagination'),
-	utils = require('../../public/src/utils');
+
+var async = require('async');
+var S = require('string');
+var nconf = require('nconf');
+var validator = require('validator');
+
+var user = require('../user');
+var meta = require('../meta');
+var topics = require('../topics');
+var posts = require('../posts');
+var privileges = require('../privileges');
+var plugins = require('../plugins');
+var helpers = require('./helpers');
+var pagination = require('../pagination');
+var utils = require('../../public/src/utils');
+
+var topicsController = {};
 
 topicsController.get = function(req, res, callback) {
-	var tid = req.params.topic_id,
-		sort = req.query.sort,
-		currentPage = parseInt(req.query.page, 10) || 1,
-		pageCount = 1,
-		userPrivileges;
+	var tid = req.params.topic_id;
+	var sort = req.query.sort;
+	var currentPage = parseInt(req.query.page, 10) || 1;
+	var pageCount = 1;
+	var userPrivileges;
 
 	if ((req.params.post_index && !utils.isNumber(req.params.post_index)) || !utils.isNumber(tid)) {
 		return callback();
@@ -128,7 +131,7 @@ topicsController.get = function(req, res, callback) {
 					url: nconf.get('relative_path') + '/category/' + data.topicData.category.slug
 				},
 				{
-					text: data.topicData.title
+					text: validator.escape(data.topicData.title)
 				}
 			];
 
@@ -187,7 +190,7 @@ topicsController.get = function(req, res, callback) {
 				},
 				{
 					property: 'og:title',
-					content: topicData.title.replace(/&amp;/g, '&')
+					content: topicData.title
 				},
 				{
 					property: 'og:description',
diff --git a/src/notifications.js b/src/notifications.js
index cb68e347ff..8d984f11c3 100644
--- a/src/notifications.js
+++ b/src/notifications.js
@@ -44,9 +44,6 @@ var async = require('async'),
 					return next(null, null);
 				}
 
-				if (notification.bodyShort) {
-					notification.bodyShort = S(notification.bodyShort).escapeHTML().s;
-				}
 				if (notification.bodyLong) {
 					notification.bodyLong = S(notification.bodyLong).escapeHTML().s;
 				}
@@ -388,9 +385,9 @@ var async = require('async'),
 						var numUsers = usernames.length;
 
 						if (numUsers === 2) {
-							notifications[modifyIndex].bodyShort = '[[' + mergeId + '_dual, ' + usernames.join(', ') + ', ' + notifications[modifyIndex].topicTitle + ']]'
+							notifications[modifyIndex].bodyShort = '[[' + mergeId + '_dual, ' + usernames.join(', ') + ', ' + notifications[modifyIndex].topicTitle + ']]';
 						} else if (numUsers > 2) {
-							notifications[modifyIndex].bodyShort = '[[' + mergeId + '_multiple, ' + usernames[0] + ', ' + (numUsers-1) + ', ' + notifications[modifyIndex].topicTitle + ']]'
+							notifications[modifyIndex].bodyShort = '[[' + mergeId + '_multiple, ' + usernames[0] + ', ' + (numUsers-1) + ', ' + notifications[modifyIndex].topicTitle + ']]';
 						}
 						break;
 				}
diff --git a/src/topics/data.js b/src/topics/data.js
index 458aac2894..92a4a89355 100644
--- a/src/topics/data.js
+++ b/src/topics/data.js
@@ -58,7 +58,7 @@ module.exports = function(Topics) {
 		if (!topic) {
 			return;
 		}
-		topic.title = validator.escape(topic.title);
+		topic.titleEscaped = validator.escape(topic.title);
 		topic.relativeTime = utils.toISOString(topic.timestamp);
 		topic.lastposttimeISO = utils.toISOString(topic.lastposttime);
 	}
diff --git a/tests/topics.js b/tests/topics.js
index bdc15643ba..ff12d84375 100644
--- a/tests/topics.js
+++ b/tests/topics.js
@@ -1,11 +1,12 @@
 'use strict';
 /*global require, before, beforeEach, after*/
 
-var	assert = require('assert'),
-	db = require('./mocks/databasemock'),
-	topics = require('../src/topics'),
-	categories = require('../src/categories'),
-	User = require('../src/user');
+var	assert = require('assert');
+var validator = require('validator');
+var db = require('./mocks/databasemock');
+var topics = require('../src/topics');
+var categories = require('../src/categories');
+var User = require('../src/user');
 
 describe('Topic\'s', function() {
 	var topic,
@@ -144,6 +145,22 @@ describe('Topic\'s', function() {
 		});
 	});
 
+	describe('Title escaping', function() {
+
+		it('should properly escape topic title', function(done) {
+			var title = '"<script>alert(\'ok1\');</script> new topic test';
+			var titleEscaped = validator.escape(title);
+			topics.post({uid: topic.userId, title: title, content: topic.content, cid: topic.categoryId}, function(err, result) {
+				assert.ifError(err);
+				topics.getTopicData(result.topicData.tid, function(err, topicData) {
+					assert.ifError(err);
+					assert.strictEqual(topicData.titleEscaped, titleEscaped);
+					assert.strictEqual(topicData.title, title);
+				});
+			});
+		});
+	});
+
 	after(function() {
 		db.flushdb();
 	});