Skip to content

Commit

Permalink
Merge pull request from GHSA-rm89-9g65-4ffr
Browse files Browse the repository at this point in the history
* Enable HTML escaping for all tables by default

* Enable HTML escaping for all tables by default

* Adds automatic escaping for bootstrap tables where custom formatter function is specified

- Intercept the row data *before* it is provided to the renderer function
- Adds a function for sanitizing nested data structure

* Sanitize form data before processing
  • Loading branch information
SchrodingersGat authored Jun 15, 2022
1 parent 57563f6 commit cd418d6
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
35 changes: 35 additions & 0 deletions InvenTree/InvenTree/static/script/inventree/inventree.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
inventreeDocReady,
inventreeLoad,
inventreeSave,
sanitizeData,
*/

function attachClipboard(selector, containerselector, textElement) {
Expand Down Expand Up @@ -273,6 +274,40 @@ function loadBrandIcon(element, name) {
}
}


/*
* Function to sanitize a (potentially nested) object.
* Iterates through all levels, and sanitizes each primitive string.
*
* Note that this function effectively provides a "deep copy" of the provided data,
* and the original data structure is unaltered.
*/
function sanitizeData(data) {
if (data == null) {
return null;
} else if (Array.isArray(data)) {
// Handle arrays
var ret = [];
data.forEach(function(val) {
ret.push(sanitizeData(val));
});
} else if (typeof(data) === 'object') {
// Handle nested structures
var nested = {};
$.each(data, function(k, v) {
nested[k] = sanitizeData(v);
});

return nested;
} else if (typeof(data) === 'string') {
// Perform string replacement
return data.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;').replace(/`/g, '&#x60;');
} else {
return data;
}
}


// Convenience function to determine if an element exists
$.fn.exists = function() {
return this.length !== 0;
Expand Down
3 changes: 3 additions & 0 deletions InvenTree/templates/js/translated/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ function constructChangeForm(fields, options) {
},
success: function(data) {

// Ensure the data are fully sanitized before we operate on it
data = sanitizeData(data);

// An optional function can be provided to process the returned results,
// before they are rendered to the form
if (options.processResults) {
Expand Down
45 changes: 45 additions & 0 deletions InvenTree/templates/js/translated/tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ $.fn.inventreeTable = function(options) {
// Extract query params
var filters = options.queryParams || options.filters || {};

options.escape = true;

// Store the total set of query params
options.query_params = filters;

Expand Down Expand Up @@ -567,6 +569,49 @@ function customGroupSorter(sortName, sortOrder, sortData) {

$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['en-US-custom']);

// Enable HTML escaping by default
$.fn.bootstrapTable.escape = true;

// Override the 'calculateObjectValue' function at bootstrap-table.js:3525
// Allows us to escape any nasty HTML tags which are rendered to the DOM
$.fn.bootstrapTable.utils._calculateObjectValue = $.fn.bootstrapTable.utils.calculateObjectValue;

$.fn.bootstrapTable.utils.calculateObjectValue = function escapeCellValue(self, name, args, defaultValue) {

var args_list = [];

if (args) {

args_list.push(args[0]);

if (name && typeof(name) === 'function' && name.name == 'formatter') {
/* This is a custom "formatter" function for a particular cell,
* which may side-step regular HTML escaping, and inject malicious code into the DOM.
*
* Here we have access to the 'args' supplied to the custom 'formatter' function,
* which are in the order:
* args = [value, row, index, field]
*
* 'row' is the one we are interested in
*/

var row = Object.assign({}, args[1]);

args_list.push(sanitizeData(row));
} else {
args_list.push(args[1]);
}

for (var ii = 2; ii < args.length; ii++) {
args_list.push(args[ii]);
}
}

var value = $.fn.bootstrapTable.utils._calculateObjectValue(self, name, args_list, defaultValue);

return value;
};

})(jQuery);

$.extend($.fn.treegrid.defaults, {
Expand Down

0 comments on commit cd418d6

Please sign in to comment.