[FIX] point_of_sale, pos_*: improve Markup

pos_*: pos_adyen, pos_six

The use of the Markup was meant to keep the formatting (mostly the line breaks) of the data
given by the payment terminals. The data was stored on the `ticket` attribute of the `Payment`
model. A security issue arose from the fact that it is possible to import orders from a file
via the debug widget.
The `ticket` attribute was initialized in the `init_from_json` method and could be injected
with some malicious code.

Solution:
Instead of replacing all line breaks by the `<br/>` tag whenever terminal data is retrieved,
we can simply store this as it is in the `ticket` attribute. We then escape the value before
replacing the line breaks when exporting the data as a Markup. With this, only our `<br/>` tags
are trusted.

closes odoo/odoo#114770

X-original-commit: 7194506648c3512dc6a80d4a92a986643e60c5d2
Related: odoo/enterprise#37962
Signed-off-by: Heinz Robin (rhe) <rhe@odoo.com>
Signed-off-by: Trinh Jacky (trj) <trj@odoo.com>
This commit is contained in:
Jacky (trj)
2023-03-09 15:54:58 +01:00
parent 1e48332176
commit ba8bba2add
3 changed files with 9 additions and 8 deletions
+4 -2
View File
@@ -12,6 +12,7 @@ import { ErrorPopup } from "./Popups/ErrorPopup";
import { ProductConfiguratorPopup } from "@point_of_sale/js/Popups/ProductConfiguratorPopup";
import { EditListPopup } from "@point_of_sale/js/Popups/EditListPopup";
import { markRaw, reactive } from "@odoo/owl";
import { escape } from "@web/core/utils/strings";
var QWeb = core.qweb;
var _t = core._t;
@@ -2578,12 +2579,13 @@ export class Payment extends PosModel {
};
}
//exports as JSON for receipt printing
export_for_printing() {
export_for_printing(){
const ticket = escape(this.ticket).replace(/\n/g, "<br />"); // formatting
return {
cid: this.cid,
amount: this.get_amount(),
name: this.name,
ticket: Markup(this.ticket),
ticket: Markup(ticket),
};
}
// If payment status is a non-empty string, then it is an electronic payment.
@@ -191,11 +191,10 @@ export const PaymentAdyen = PaymentInterface.extend({
_convert_receipt_info: function (output_text) {
return output_text.reduce(function (acc, entry) {
var params = new URLSearchParams(entry.Text);
if (params.get("name") && !params.get("value")) {
return acc + _.str.sprintf("<br/>%s", params.get("name"));
return acc + _.str.sprintf("\n%s", params.get("name"));
} else if (params.get("name") && params.get("value")) {
return acc + _.str.sprintf("<br/>%s: %s", params.get("name"), params.get("value"));
return acc + _.str.sprintf("\n%s: %s", params.get("name"), params.get("value"));
}
return acc;
+3 -3
View File
@@ -4,6 +4,7 @@
import core from "web.core";
import { PaymentInterface } from "@point_of_sale/js/payment";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { escape } from "@web/core/utils/strings";
var _t = core._t;
@@ -152,18 +153,17 @@ export const PaymentSix = PaymentInterface.extend({
_printReceipts: function (receipts) {
_.forEach(receipts, (receipt) => {
var value = receipt.value.replace(/\n/g, "<br />");
if (
receipt.recipient === timapi.constants.Recipient.merchant &&
this.pos.env.proxy.printer
) {
this.pos.env.proxy.printer.print_receipt(
"<div class='pos-receipt'><div class='pos-payment-terminal-receipt'>" +
value +
escape(receipt.value).replace(/\n/g, "<br />") +
"</div></div>"
);
} else if (receipt.recipient === timapi.constants.Recipient.cardholder) {
this.pos.get_order().selected_paymentline.set_receipt_info(value);
this.pos.get_order().selected_paymentline.set_receipt_info(receipt.value);
}
});
},