Skip to content

Commit aae1517

Browse files
authored
Merge branch 'master' into QT-344
2 parents 053b9fe + 98bb56c commit aae1517

File tree

5 files changed

+45
-50
lines changed

5 files changed

+45
-50
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
## Version 25.03.xx
22
Fixes:
33
- [push] Fixed timeout setting
4+
- [security] Fixed injection possibility on res.expose
5+
6+
Enterprise Fixes:
7+
- [groups] Add logs for user updates
8+
- [surveys] Change question map log to debug log
49

510
Dependencies:
611
- Bump axios from 1.12.2 to 1.13.1 in /plugins/cognito

frontend/express/app.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,10 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_
438438
next();
439439
});
440440

441-
app.use('*.svg', function(req, res, next) {
442-
res.setHeader('Content-Type', 'image/svg+xml; charset=UTF-8');
441+
app.use(function(req, res, next) {
442+
if (req.path.endsWith('.svg')) {
443+
res.setHeader('Content-Type', 'image/svg+xml; charset=UTF-8');
444+
}
443445
next();
444446
});
445447

frontend/express/libs/express-expose.js

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ function renderNamespace(str) {
157157
function renderObject(obj, namespace) {
158158
return Object.keys(obj).map(function(key) {
159159
var val = obj[key];
160-
return namespace + '["' + key + '"] = ' + string(val) + ';';
160+
return namespace + '["' + escape_js_string(key) + '"] = ' + string(val) + ';';
161161
}).join('\n');
162162
}
163163

@@ -180,61 +180,49 @@ function string(obj) {
180180
}
181181
else if ('[object Object]' === Object.prototype.toString.call(obj)) {
182182
return '{' + Object.keys(obj).map(function(key) {
183-
return '"' + key + '":' + string(obj[key]);
183+
return '"' + escape_js_string(key) + '":' + string(obj[key]);
184184
}).join(', ') + '}';
185185
}
186186
else {
187-
obj = escape_html(JSON.stringify(obj));
187+
obj = JSON.stringify(obj);
188188
if (obj) {
189+
// Only escape things that could break out of script context
189190
obj = obj.replace(/<\/script>/ig, '</scr"+"ipt>');
191+
obj = obj.replace(/<!--/g, '<\\!--');
192+
obj = obj.replace(/\u2028/g, '\\u2028'); // Line separator
193+
obj = obj.replace(/\u2029/g, '\\u2029'); // Paragraph separator
190194
}
191195
return obj;
192196
}
193197
}
194198

195-
var matchHtmlRegExp = /[<>]/;
196-
197199
/**
198-
* Escape special characters in the given string of html.
200+
* Escape special characters that could break JavaScript string context
199201
*
200-
* @param {string} str - The string to escape for inserting into HTML
202+
* @param {string} str - The string to escape
201203
* @return {string} escaped string
202204
* @public
203205
*/
204-
function escape_html(str) {
205-
str = '' + str;
206-
var match = matchHtmlRegExp.exec(str);
207-
208-
if (!match) {
206+
function escape_js_string(str) {
207+
if (typeof str !== 'string') {
209208
return str;
210209
}
211210

212-
var escape;
213-
var html = '';
214-
var index = 0;
215-
var lastIndex = 0;
216-
217-
for (index = match.index; index < str.length; index++) {
218-
switch (str.charCodeAt(index)) {
219-
case 60: // <
220-
escape = '&lt;';
221-
break;
222-
case 62: // >
223-
escape = '&gt;';
224-
break;
225-
default:
226-
continue;
227-
}
228-
229-
if (lastIndex !== index) {
230-
html += str.substring(lastIndex, index);
231-
}
232-
233-
lastIndex = index + 1;
234-
html += escape;
235-
}
236-
237-
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
211+
return str
212+
.replace(/\\/g, '\\\\') // Backslash
213+
.replace(/"/g, '\\"') // Double quote
214+
.replace(/'/g, "\\'") // Single quote
215+
.replace(/`/g, '\\`') // Backtick (template literal)
216+
.replace(/\$/g, '\\$') // Dollar sign (template literal)
217+
.replace(/\n/g, '\\n') // Newline
218+
.replace(/\r/g, '\\r') // Carriage return
219+
.replace(/\t/g, '\\t') // Tab
220+
.replace(/\f/g, '\\f') // Form feed
221+
.replace(/\v/g, '\\v') // Vertical tab
222+
.replace(/\0/g, '\\0') // Null character
223+
.replace(/[\u0000-\u001F\u007F-\u009F]/g, function(ch) {
224+
return '\\u' + ('0000' + ch.charCodeAt(0).toString(16)).slice(-4);
225+
});
238226
}
239227

240228
exports = module.exports = function(app) {

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"ejs": "3.1.10",
6060
"errorhandler": "1.5.1",
6161
"express": "4.21.2",
62-
"express-rate-limit": "8.2.0",
62+
"express-rate-limit": "8.2.1",
6363
"express-session": "1.18.2",
6464
"form-data": "^4.0.0",
6565
"formidable": "2.1.3",
@@ -92,7 +92,7 @@
9292
"offline-geocoder": "git+https://github.com/Countly/offline-geocoder.git",
9393
"properties-parser": "0.6.0",
9494
"puppeteer": "^24.6.1",
95-
"sass": "1.93.2",
95+
"sass": "1.93.3",
9696
"semver": "^7.7.1",
9797
"sharp": "^0.34.2",
9898
"sqlite3": "^5.1.7",

0 commit comments

Comments
 (0)