Skip to content

Commit f5e0d49

Browse files
authored
Merge pull request from GHSA-7p8h-86p5-wv3p
- Fix several XSS vulnerabilities
2 parents 440f0e5 + 0fa67c7 commit f5e0d49

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

Diff for: lib/filters.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ exports.to_display = function (input) {
6666
&& input._id
6767
) {
6868
retHTML += '<div class="tooDamnBig" doc_id="' + encodeURIComponent(JSON.stringify(input._id)) + '" '
69-
+ 'doc_prop="' + input.attribu + '" title="Max prop size: ' + input.maxSize + '">';
69+
+ 'doc_prop="' + entifyGTLTAmp(input.attribu) + '" title="Max prop size: ' + input.maxSize + '">';
7070
retHTML += input.display + '<br>~' + input.humanSz;
71-
retHTML += '<br>Preview:' + input.preview;
71+
retHTML += '<br>Preview:' + entifyGTLTAmp(input.preview);
7272
retHTML += '<br>Click to fetch this property';
7373
retHTML += '</div>';
7474
return retHTML;
@@ -87,9 +87,9 @@ exports.to_display = function (input) {
8787
&& input._id
8888
) {
8989
retHTML += '<div class="tooDamnBig" doc_id="' + encodeURIComponent(JSON.stringify(input._id)) + '" '
90-
+ 'doc_prop="' + input.attribu + '" title="Max row size: ' + input.maxSize + '">';
91-
retHTML += input.display + '<br>' + input.attribu + ': ~' + input.humanSz;
92-
retHTML += '<br>Preview:' + input.preview;
90+
+ 'doc_prop="' + entifyGTLTAmp(input.attribu) + '" title="Max row size: ' + input.maxSize + '">';
91+
retHTML += input.display + '<br>' + entifyGTLTAmp(input.attribu) + ': ~' + input.humanSz;
92+
retHTML += '<br>Preview:' + entifyGTLTAmp(input.preview);
9393
retHTML += '<br>Click to fetch this property';
9494
retHTML += '</div>';
9595
return retHTML;
@@ -105,7 +105,7 @@ exports.to_display = function (input) {
105105
|| input.substr(0, 23) === 'data:image/jpeg;base64,'
106106
)
107107
) {
108-
return '<img src="' + input + '" style="max-height:100%; max-width:100%; "/>';
108+
return '<img src="' + entifyGTLTAmp(input) + '" style="max-height:100%; max-width:100%; "/>';
109109
}
110110

111111
// Audio inline
@@ -116,7 +116,7 @@ exports.to_display = function (input) {
116116
|| input.substr(0, 22) === 'data:audio/mp3;base64,'
117117
)
118118
) {
119-
return '<audio controls style="width:45px;" src="' + input + '">Your browser does not support the audio element.</audio>';
119+
return '<audio controls style="width:45px;" src="' + entifyGTLTAmp(input) + '">Your browser does not support the audio element.</audio>';
120120
}
121121

122122
// Video inline
@@ -128,7 +128,8 @@ exports.to_display = function (input) {
128128
|| input.substr(0, 22) === 'data:video/ogv;base64,'
129129
)
130130
) {
131-
return '<video controls><source type="' + input.substring(input.indexOf(':') + 1, input.indexOf(';')) + '" src="' + input + '"/>'
131+
const videoFormat = input.match(/^data:(.*);base64/)[1];
132+
return '<video controls><source type="' + videoFormat + '" src="' + entifyGTLTAmp(input) + '"/>'
132133
+ 'Your browser does not support the video element.</video>';
133134
}
134135

Diff for: lib/scripts/collection.js

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import $ from 'jquery';
22
import renderjson from 'renderjson';
33
import CodeMirror from './codeMirrorLoader';
4+
import escapeHtml from './escapeHtml';
45

56
function getParameterByName(name) {
67
name = name.replace(/\[/, '\\[').replace(/[\]]/, '\\]');
@@ -137,7 +138,7 @@ $(() => {
137138
// Set the element with spinner for now
138139
target.html(spinner);
139140

140-
$.get(`${makeCollectionUrl()}${encodeURIComponent(_id)}/${prop}`, function (input) {
141+
function renderProp(input) {
141142
// Images inline
142143
if (
143144
typeof input === 'string'
@@ -148,7 +149,7 @@ $(() => {
148149
|| input.substr(0, 23) === 'data:image/jpeg;base64,'
149150
)
150151
) {
151-
input = '<img src="' + input + '" style="max-height:100%; max-width:100%; "/>';
152+
return `<img src="${escapeHtml(input)}" style="max-height:100%; max-width:100%; "/>`;
152153
}
153154

154155
// Audio inline
@@ -160,7 +161,7 @@ $(() => {
160161
|| input.substr(0, 22) === 'data:audio/mp3;base64,'
161162
)
162163
) {
163-
input = '<audio controls style="width:45px;" src="' + input + '">Your browser does not support the audio element.</audio>';
164+
return `<audio controls style="width:45px;" src="${escapeHtml(input)}">Your browser does not support the audio element.</audio>`;
164165
}
165166

166167
// Video inline
@@ -172,16 +173,22 @@ $(() => {
172173
|| input.substr(0, 22) === 'data:video/ogv;base64,'
173174
)
174175
) {
175-
input = '<video controls><source type="' + input.substring(input.indexOf(':') + 1, input.indexOf(';')) + '" src="' + input + '"/>'
176-
+ 'Your browser does not support the video element.</video>';
176+
const videoFormat = input.match(/^data:(.*);base64/)[1];
177+
return `<video controls><source type="${escapeHtml(videoFormat)}" src="${escapeHtml(input)}"/>
178+
+ 'Your browser does not support the video element.</video>`;
177179
}
178-
179180
if (typeof input === 'object' && (input.toString() === '[object Object]' || input.toString().substr(0, 7) === '[object')) {
180-
input = renderjson(input);
181+
return renderjson(input);
181182
}
182183

184+
// treat unknown data as escaped string
185+
return escapeHtml(input.toString());
186+
}
187+
188+
$.get(`${makeCollectionUrl()}${encodeURIComponent(_id)}/${prop}`, function (prop) {
189+
prop = renderProp(prop);
183190
// Set the element with gotten datas
184-
target.parent().html(input);
191+
target.parent().html(prop);
185192

186193
// Set original scroll position
187194
$('.tableWrapper').scrollLeft(leftScroll);

Diff for: lib/scripts/escapeHtml.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function (html) {
2+
// Turn < ? > into HTML entities, so data doesn't get interpreted by the browser
3+
return html.replace(/&/g, '&amp;')
4+
.replace(/</g, '&lt;')
5+
.replace(/>/g, '&gt;')
6+
.replace(/"/g, '&quot;')
7+
.replace(/'/g, '&apos;');
8+
}

0 commit comments

Comments
 (0)