CVE-2020-15253 (JavaScript, published 2020-10-14T19:15Z)
Description: value: Versions of Grocy <= 2.7.1 are vulnerable to Cross-Site Scripting via the Create Shopping List module, that is rendered upon deleting that Shopping List. The issue was also found in users, batteries, chores, equipment, locations, quantity units, shopping locations, tasks, taskcategories, product groups, recipes and products. Authentication is required to exploit these issues and Grocy should not be publicly exposed. The linked reference details a proof-of-concept.
Severity: LOW (CVSS v3 base score: 4.8)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/grocy/grocy
Files changed:
public/js/extensions.js
public/viewjs/batteries.js
public/viewjs/chores.js
public/viewjs/components/productpicker.js
public/viewjs/equipment.js
public/viewjs/locations.js
public/viewjs/mealplan.js
public/viewjs/productgroups.js
public/viewjs/products.js
public/viewjs/quantityunits.js
public/viewjs/recipeform.js
public/viewjs/recipes.js
public/viewjs/shoppinglist.js
public/viewjs/shoppinglocations.js
public/viewjs/taskcategories.js
public/viewjs/tasks.js
public/viewjs/userentities.js
public/viewjs/userfields.js
public/viewjs/users.js
Commit message: Excape HTML (where needed, for bootbox) (references #996)


Vulnerable code:
	var objectName = $(e.currentTarget).attr('data-battery-name');
	var objectName = $(e.currentTarget).attr('data-chore-name');
				message: __t('"%s" could not be resolved to a product, how do you want to proceed?', input),
	var objectName = $(e.currentTarget).attr('data-equipment-name');
	var objectName = $(e.currentTarget).attr('data-location-name');
	var objectName = $(e.currentTarget).attr('data-recipe-name');
	var objectName = $(e.currentTarget).attr('data-recipe-name');
	var objectName = $(e.currentTarget).attr('data-group-name');
	var objectName = $(e.currentTarget).attr('data-product-name');
	var objectName = $(e.currentTarget).attr('data-quantityunit-name');
	var objectName = $(e.currentTarget).attr('data-recipe-pos-name');
	var objectName = $(e.currentTarget).attr('data-recipe-include-name');
	var note = $(e.currentTarget).attr('data-recipe-pos-note');
	var objectName = $(e.currentTarget).attr('data-recipe-name');
	var objectName = $(e.currentTarget).attr('data-recipe-name');
	var objectName = $(e.currentTarget).attr('data-recipe-name');
	var objectName = $("#selected-shopping-list option:selected").text();
		message: __t('Are you sure to empty shopping list "%s"?', $("#selected-shopping-list option:selected").text()),
	var objectName = $(e.currentTarget).attr('data-shoppinglocation-name');
	var objectName = $(e.currentTarget).attr('data-category-name');
	var objectName = $(e.currentTarget).attr('data-task-name');
	var objectName = $(e.currentTarget).attr('data-userentity-name');
	var objectName = $(e.currentTarget).attr('data-userfield-name');
	var objectName = $(e.currentTarget).attr('data-user-username');

Fixed code:




function SanitizeHtml(input)
{
	return $("<div/>").text(input).html();
}
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-battery-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-chore-name'));
				message: __t('"%s" could not be resolved to a product, how do you want to proceed?', SanitizeHtml(input)),
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-equipment-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-location-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-group-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-product-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-quantityunit-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-pos-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-include-name'));
	var note = SanitizeHtml($(e.currentTarget).attr('data-recipe-pos-note'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-recipe-name'));
	var objectName = SanitizeHtml($("#selected-shopping-list option:selected").text());
		message: __t('Are you sure to empty shopping list "%s"?', SanitizeHtml($("#selected-shopping-list option:selected").text())),
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-shoppinglocation-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-category-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-task-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-userentity-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-userfield-name'));
	var objectName = SanitizeHtml($(e.currentTarget).attr('data-user-username'));