fix(helpdesk): use strict input validation for all user-supplied customerNo in OData filters

Replaces escapeODataTrustedLiteral with escapeODataStrictUserInput for all
customerNo parameters that originate from HTTP request input. The trusted
literal escape (quote-only) remains for BC-sourced values like customerName.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 15:07:40 +02:00
parent 15e12c5215
commit a0cb345e04

View File

@@ -453,7 +453,7 @@ class BcODataGateway
return []; return [];
} }
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = "Customer_No eq '" . $escaped . "'"; $filter = "Customer_No eq '" . $escaped . "'";
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV)
. '?$filter=' . rawurlencode($filter) . '?$filter=' . rawurlencode($filter)
@@ -541,7 +541,7 @@ class BcODataGateway
return []; return [];
} }
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = "Customer_No eq '" . $escaped . "'"; $filter = "Customer_No eq '" . $escaped . "'";
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV)
. '?$filter=' . rawurlencode($filter) . '?$filter=' . rawurlencode($filter)
@@ -572,7 +572,7 @@ class BcODataGateway
return []; return [];
} }
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = "Customer_No eq '" . $escaped . "'"; $filter = "Customer_No eq '" . $escaped . "'";
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_TICKETS_LV)
. '?$filter=' . rawurlencode($filter) . '?$filter=' . rawurlencode($filter)
@@ -756,7 +756,7 @@ class BcODataGateway
*/ */
private function fetchContractsByCustomerField(string $customerNo, string $customerField, string $select): array private function fetchContractsByCustomerField(string $customerNo, string $customerField, string $select): array
{ {
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = $customerField . " eq '" . $escaped . "'"; $filter = $customerField . " eq '" . $escaped . "'";
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_CONTRACTS) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_CONTRACTS)
. '?$filter=' . rawurlencode($filter) . '?$filter=' . rawurlencode($filter)
@@ -784,7 +784,7 @@ class BcODataGateway
return []; return [];
} }
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = "Customer_No eq '" . $escaped . "'"; $filter = "Customer_No eq '" . $escaped . "'";
$select = 'Header_No,Line_No,PI_Header_State,PI_Header_Description,Type,Description,Quantity,Unit_of_Measure_Code,Unit_Price,Line_Discount_Percent,Line_Amount,Line_State,Starting_Date,Ending_Date,Position,Attached_to_Line_No'; $select = 'Header_No,Line_No,PI_Header_State,PI_Header_Description,Type,Description,Quantity,Unit_of_Measure_Code,Unit_Price,Line_Discount_Percent,Line_Amount,Line_State,Starting_Date,Ending_Date,Position,Attached_to_Line_No';
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_CONTRACT_LINES) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_CONTRACT_LINES)
@@ -813,7 +813,7 @@ class BcODataGateway
return []; return [];
} }
$escaped = $this->escapeODataTrustedLiteral($customerNo); $escaped = $this->escapeODataStrictUserInput($customerNo);
$filter = "Customer_No eq '" . $escaped . "'"; $filter = "Customer_No eq '" . $escaped . "'";
$select = 'Entry_No,Appointment_Date,Customer_No,Customer_Name,Salesperson_Code,Comment,Released_by,Release_Date'; $select = 'Entry_No,Appointment_Date,Customer_No,Customer_Name,Salesperson_Code,Comment,Released_by,Release_Date';
$url = $this->settingsGateway->buildEntityUrl(self::ENTITY_MEETINGS) $url = $this->settingsGateway->buildEntityUrl(self::ENTITY_MEETINGS)