diff --git a/CHANGELOG.md b/CHANGELOG.md index aec1538c..052a11fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## HEAD +### Bug fixes 🐛 + +- Fix potential XSS when rendering place name [#547](https://github.com/mapbox/mapbox-gl-geocoder/pull/547) + ## 5.1.1 ### Dependency update diff --git a/lib/index.js b/lib/index.js index 971eea1d..23eabdbd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -93,6 +93,16 @@ function MapboxGeocoder(options) { this.geolocation = new Geolocation(); } +function escapeHtml(str) { + if (!str) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + MapboxGeocoder.prototype = { options: { zoom: 16, @@ -116,7 +126,7 @@ MapboxGeocoder.prototype = { return item.place_name }, render: function(item) { - var placeName = item.place_name.split(','); + var placeName = escapeHtml(item.place_name).split(','); return '
' + placeName[0]+ '
' + placeName.splice(1, placeName.length).join(',') + '
'; } }, diff --git a/test/test.geocoder.js b/test/test.geocoder.js index 5dcdc7d2..922d408c 100644 --- a/test/test.geocoder.js +++ b/test/test.geocoder.js @@ -40,6 +40,22 @@ test('geocoder', function(tt) { t.end(); }); + tt.test('rendered place name is HTML-sanitized', function(t){ + t.plan(2); + + const html = ''; // should not render this as-is! + const escapedHtml = '<script>alert(1)</script>'; + + var fixture = { + id: 'abc123', + place_name: html + } + + const rendered = geocoder.options.render(fixture); + t.ok(rendered.indexOf(html) === -1, 'rendered result does not contain original dangerous HTML'); + t.ok(rendered.indexOf(escapedHtml) > 0, 'rendered result contains escaped version of HTML'); + }) + tt.test('set/get input', function(t) { t.plan(4) setup({ proximity: { longitude: -79.45, latitude: 43.65 } });