sanitize csv output
MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -920,6 +920,8 @@ export default class UtilsService {
// Get the data
req.query.Skip = skip.toString();
data = await handleGetData(req);
+ // Sanitize against csv formula injection
+ data.result = Utils.sanitizeCSVExport(data.result);
// Get CSV data
const csvData = handleConvertToCSV(req, data.result, (skip === 0));
// Send Transactions

MODIFY
src/utils/Constants.ts
src/utils/Constants.ts
@@ -307,6 +307,9 @@ export default class Constants {
public static readonly REGEX_URL_PATTERN = /^(?:https?|wss?):\/\/((?:[\w-]+)(?:\.[\w-]+)*)(?:[\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?$/;
public static readonly MAX_GPS_DISTANCE_METERS = 40000000; // Earth
+ public static readonly CSV_CHARACTERS_TO_ESCAPE = /^[+\-@=].*$/;
+ public static readonly CSV_ESCAPING_CHARACTER = '\'';
+
public static readonly EXCEPTION_JSON_KEYS_IN_SENSITIVE_DATA = Object.freeze([
'stack'
]);

MODIFY
src/utils/Utils.ts
src/utils/Utils.ts
@@ -872,6 +872,10 @@ export default class Utils {
return !Object.keys(obj).length;
}
+ public static isEmptyString(str: string): boolean {
+ return str ? str.length === 0 : true;
+ }
+
public static findDuplicatesInArray(arr: any[]): any[] {
const sorted_arr = arr.slice().sort();
const results: any[] = [];
@@ -1556,4 +1560,29 @@ export default class Utils {
public static unescapeCsvValue(value: any): void {
// double quotes are handle by csvToJson
}
+
+ public static sanitizeCSVExport(data: any): any {
+ if (!data || typeof data === 'number' || typeof data === 'bigint' || typeof data === 'symbol' || Utils.isBoolean(data) || typeof data === 'function') {
+ return data;
+ } else if (typeof data === 'string') {
+ // If the data is a string and starts with the csv characters initiating the formula parsing, then escape
+ if (!Utils.isEmptyString(data)) {
+ data = data.replace(Constants.CSV_CHARACTERS_TO_ESCAPE, Constants.CSV_ESCAPING_CHARACTER + data);
+ }
+ return data;
+ } else if (Array.isArray(data)) {
+ // If the data is an array, apply the sanitizeCSVExport function for each item
+ const sanitizedData = [];
+ for (const item of data) {
+ sanitizedData.push(Utils.sanitizeCSVExport(item));
+ }
+ return sanitizedData;
+ } else if (typeof data === 'object') {
+ // If the data is an object, apply the sanitizeCSVExport function for each attribute
+ for (const key of Object.keys(data)) {
+ data[key] = Utils.sanitizeCSVExport(data[key]);
+ }
+ return data;
+ }
+ }
}

sanitize csv output