Merge pull request #221 from copenhagentruckwash/fix-system-search-associations-vulnerability
Prevent association expansion from bypassing own-only access
This commit is contained in:
@@ -207,25 +207,28 @@ class system_search_service
|
||||
$activeTypes,
|
||||
$this->associationEntityTypes()
|
||||
));
|
||||
foreach ($customerNumbers as $customerNumber) {
|
||||
$associated = $this->executeLexicalSearch(
|
||||
$associationTypes,
|
||||
[(string)$customerNumber],
|
||||
[],
|
||||
$ownOnlyTypes,
|
||||
$ownCustomerNumber,
|
||||
$permissionsCatalogAll,
|
||||
$permissionsCatalogOwn,
|
||||
$moduleConfigVisibility,
|
||||
[$customerNumber]
|
||||
);
|
||||
foreach ($associated as &$item) {
|
||||
if (!isset($item['association_reason'])) {
|
||||
$item['association_reason'] = 'customer:' . $customerNumber;
|
||||
$associationTypes = array_values(array_diff($associationTypes, $ownOnlyTypes));
|
||||
if (!empty($associationTypes)) {
|
||||
foreach ($customerNumbers as $customerNumber) {
|
||||
$associated = $this->executeLexicalSearch(
|
||||
$associationTypes,
|
||||
[(string)$customerNumber],
|
||||
[],
|
||||
$ownOnlyTypes,
|
||||
$ownCustomerNumber,
|
||||
$permissionsCatalogAll,
|
||||
$permissionsCatalogOwn,
|
||||
$moduleConfigVisibility,
|
||||
[$customerNumber]
|
||||
);
|
||||
foreach ($associated as &$item) {
|
||||
if (!isset($item['association_reason'])) {
|
||||
$item['association_reason'] = 'customer:' . $customerNumber;
|
||||
}
|
||||
$item['score'] = max((int)$item['score'], 35);
|
||||
}
|
||||
$item['score'] = max((int)$item['score'], 35);
|
||||
$initialResults = $this->mergeResults($initialResults, $associated);
|
||||
}
|
||||
$initialResults = $this->mergeResults($initialResults, $associated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,6 +385,30 @@ it('caps AI-driven expanded terms to prevent query amplification', function ():
|
||||
expect($maxLen)->toBeLessThanOrEqual(64);
|
||||
});
|
||||
|
||||
it('does not expand associations for own-only entity types', function (): void {
|
||||
$parser = new FakeSystemSearchIntentParser();
|
||||
$service = new TestableSystemSearchService($parser, [
|
||||
[[
|
||||
'entity_type' => 'customers',
|
||||
'entity_id' => '10',
|
||||
'title' => 'Acme',
|
||||
'customer_number' => 1234,
|
||||
'score' => 80,
|
||||
]],
|
||||
[],
|
||||
]);
|
||||
|
||||
$service->search([
|
||||
'query' => 'acme',
|
||||
'allowed_types' => ['customers', 'orders'],
|
||||
'own_only_types' => ['orders'],
|
||||
'own_customer_number' => 4444,
|
||||
'include_associations' => true,
|
||||
]);
|
||||
|
||||
expect(count($service->lexicalCalls))->toBe(1);
|
||||
});
|
||||
|
||||
it('expands danish discount wording into lexical discount synonyms', function (): void {
|
||||
$parser = new FakeSystemSearchIntentParser();
|
||||
$service = new TestableSystemSearchService($parser, [[
|
||||
|
||||
Reference in New Issue
Block a user