Skip to content

Commit 3f6cce2

Browse files
authored
Merge pull request #1524 from algolia/bugfix/MAGE-932
BUG: Client side encoding for front end XSS protection on InstantSearch search box
2 parents 251c3f4 + f21740a commit 3f6cce2

File tree

2 files changed

+30
-22
lines changed

2 files changed

+30
-22
lines changed

view/frontend/web/instantsearch.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,14 @@ define(
352352
container: instant_selector,
353353
placeholder: algoliaConfig.translations.searchFor,
354354
showSubmit: false,
355-
queryHook: function (inputValue, search) {
356-
if (algoliaConfig.isSearchPage && algoliaConfig.request.categoryId.length <= 0 && algoliaConfig.request.landingPageId.length <= 0) {
357-
$(".page-title-wrapper span.base").html(algoliaConfig.translations.searchTitle + ": '" + algolia.htmlspecialcharsDecode(inputValue) + "'");
355+
queryHook: (inputValue, search) => {
356+
const encodedHtml = algolia.htmlspecialcharsEncode(inputValue);
357+
if (algoliaConfig.isSearchPage
358+
&& !algoliaConfig.request.categoryId
359+
&& !algoliaConfig.request.landingPageId.length) {
360+
$(".page-title-wrapper span.base").html(algoliaConfig.translations.searchTitle + ": '" + encodedHtml + "'");
358361
}
359-
return search(inputValue);
362+
return search(inputValue);
360363
}
361364
}
362365
}

view/frontend/web/internals/common.js

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
define(['jquery', 'algoliaBundle'], function ($, algoliaBundle) {
2+
// Character maps supplied for more performant Regex ops
3+
const SPECIAL_CHAR_ENCODE_MAP = {
4+
'&': '&amp;',
5+
'<': '&lt;',
6+
'>': '&gt;',
7+
'"': '&quot;',
8+
"'": '&#039;'
9+
};
10+
11+
/// Reverse key / value pair
12+
const SPECIAL_CHAR_DECODE_MAP = Object.entries(SPECIAL_CHAR_ENCODE_MAP).reduce((acc, [key, value]) => {
13+
acc[value] = key;
14+
return acc;
15+
}, {});
216

3-
window.algolia = {
17+
window.algolia = {
418
deprecatedHooks: [
519
'beforeAutocompleteProductSourceOptions',
620
'beforeAutocompleteSources'
@@ -64,23 +78,14 @@ define(['jquery', 'algoliaBundle'], function ($, algoliaBundle) {
6478

6579
return data;
6680
},
67-
htmlspecialcharsDecode: function(string) {
68-
var unescapedString = string,
69-
specialchars = [
70-
[ '"', '&quot;' ],
71-
[ '>', '&gt;' ],
72-
[ '<', '&lt;' ],
73-
[ '&', '&amp;' ],
74-
[ "'", '&#39;' ]
75-
];
76-
77-
var len = specialchars.length;
78-
for (var i=0; i<len; i++) {
79-
unescapedString = unescapedString.replace(new RegExp(specialchars[i][1], 'g'), specialchars[i][0]);
80-
}
81-
82-
return unescapedString;
83-
}
81+
htmlspecialcharsDecode: string => {
82+
const regex = new RegExp(Object.keys(SPECIAL_CHAR_DECODE_MAP).join('|'), 'g');
83+
return string.replace(regex, m => SPECIAL_CHAR_DECODE_MAP[m]);
84+
},
85+
htmlspecialcharsEncode: string => {
86+
const regex = new RegExp(`[${Object.keys(SPECIAL_CHAR_ENCODE_MAP).join('')}]`, 'g');
87+
return string.replace(regex, (m) => SPECIAL_CHAR_ENCODE_MAP[m]);
88+
}
8489
};
8590

8691
window.isMobile = function () {

0 commit comments

Comments
 (0)