VYPR
Critical severityNVD Advisory· Published Jan 16, 2024· Updated Jun 2, 2025

Blind SQL-injection in DAL aggregations in Shopware

CVE-2024-22406

Description

Shopware is an open headless commerce platform. The Shopware application API contains a search functionality which enables users to search through information stored within their Shopware instance. The searches performed by this function can be aggregated using the parameters in the “aggregations” object. The ‘name’ field in this “aggregations” object is vulnerable SQL-injection and can be exploited using time-based SQL-queries. This issue has been addressed and users are advised to update to Shopware 6.5.7.4. For older versions of 6.1, 6.2, 6.3 and 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
shopware/corePackagist
< 6.5.7.46.5.7.4
shopware/platformPackagist
< 6.5.7.46.5.7.4

Affected products

1

Patches

2
5005213e609f

NEXT-32887 - Improve SQL escaping in DAL

https://github.com/shopware/shopwareSoner SayakciJan 3, 2024via ghsa
5 files changed · +39 33
  • phpstan-baseline.neon+0 10 modified
    @@ -4920,16 +4920,6 @@ parameters:
     			count: 1
     			path: src/Core/Framework/DataAbstractionLayer/Command/CreateHydratorCommand.php
     
    -		-
    -			message: "#^Anonymous variable in a `\\$field\\-\\>\\.\\.\\.\\(\\)` method call can lead to false dead methods\\. Make sure the variable type is known$#"
    -			count: 1
    -			path: src/Core/Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/JsonFieldAccessorBuilder.php
    -
    -		-
    -			message: "#^Method Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\Dbal\\\\FieldAccessorBuilder\\\\JsonFieldAccessorBuilder\\:\\:getField\\(\\) has parameter \\$fields with no value type specified in iterable type array\\.$#"
    -			count: 1
    -			path: src/Core/Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/JsonFieldAccessorBuilder.php
    -
     		-
     			message: "#^Method Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\Dbal\\\\QueryBuilder\\:\\:getStates\\(\\) return type has no value type specified in iterable type array\\.$#"
     			count: 1
    
  • src/Core/Framework/DataAbstractionLayer/Dbal/EntityAggregator.php+15 15 modified
    @@ -293,11 +293,11 @@ private function parseDateHistogramAggregation(
             $query->addGroupBy($groupBy);
     
             $key = $aggregation->getName() . '.key';
    -        $query->addSelect(sprintf('MIN(%s) as `%s`', $accessor, $key));
    +        $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($key)));
     
             $key = $aggregation->getName() . '.count';
             $countAccessor = $this->queryHelper->getFieldAccessor('id', $definition, $definition->getEntityName(), $context);
    -        $query->addSelect(sprintf('COUNT(%s) as `%s`', $countAccessor, $key));
    +        $query->addSelect(sprintf('COUNT(%s) as %s', $countAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             if ($aggregation->getSorting()) {
                 $this->addSorting($aggregation->getSorting(), $definition, $query, $context);
    @@ -326,12 +326,12 @@ private function parseTermsAggregation(
                 $keyAccessor = 'LOWER(HEX(' . $keyAccessor . '))';
             }
     
    -        $query->addSelect(sprintf('%s as `%s`', $keyAccessor, $key));
    +        $query->addSelect(sprintf('%s as %s', $keyAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             $key = $aggregation->getName() . '.count';
     
             $countAccessor = $this->queryHelper->getFieldAccessor('id', $definition, $definition->getEntityName(), $context);
    -        $query->addSelect(sprintf('COUNT(%s) as `%s`', $countAccessor, $key));
    +        $query->addSelect(sprintf('COUNT(%s) as %s', $countAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             if ($aggregation->getLimit()) {
                 $query->setMaxResults($aggregation->getLimit());
    @@ -354,7 +354,7 @@ private function parseAvgAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('AVG(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('AVG(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseSumAggregation(
    @@ -365,7 +365,7 @@ private function parseSumAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('SUM(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('SUM(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseMaxAggregation(
    @@ -376,7 +376,7 @@ private function parseMaxAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('MAX(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('MAX(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseMinAggregation(
    @@ -387,7 +387,7 @@ private function parseMinAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('MIN(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseCountAggregation(
    @@ -398,7 +398,7 @@ private function parseCountAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('COUNT(DISTINCT %s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('COUNT(DISTINCT %s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseStatsAggregation(
    @@ -410,16 +410,16 @@ private function parseStatsAggregation(
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
             if ($aggregation->fetchAvg()) {
    -            $query->addSelect(sprintf('AVG(%s) as `%s.avg`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('AVG(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.avg')));
             }
             if ($aggregation->fetchMin()) {
    -            $query->addSelect(sprintf('MIN(%s) as `%s.min`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.min')));
             }
             if ($aggregation->fetchMax()) {
    -            $query->addSelect(sprintf('MAX(%s) as `%s.max`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('MAX(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.max')));
             }
             if ($aggregation->fetchSum()) {
    -            $query->addSelect(sprintf('SUM(%s) as `%s.sum`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('SUM(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.sum')));
             }
         }
     
    @@ -445,7 +445,7 @@ private function parseRangeAggregation(
                     $sum .= sprintf(' AND %s < %f', $accessor, $range['to']);
                 }
     
    -            $query->addSelect(sprintf('SUM(%s) as `%s.%s`', $sum, $aggregation->getName(), $id));
    +            $query->addSelect(sprintf('SUM(%s) as %s', $sum, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.' . $id)));
             }
         }
     
    @@ -459,7 +459,7 @@ private function parseEntityAggregation(
             $query->addGroupBy($accessor);
     
             $accessor = 'LOWER(HEX(' . $accessor . '))';
    -        $query->addSelect(sprintf('%s as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('%s as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         /**
    
  • src/Core/Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/JsonFieldAccessorBuilder.php+6 3 modified
    @@ -58,9 +58,9 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
             }
     
             $jsonValueExpr = sprintf(
    -            'JSON_EXTRACT(`%s`.`%s`, %s)',
    -            $root,
    -            $field->getStorageName(),
    +            'JSON_EXTRACT(%s.%s, %s)',
    +            EntityDefinitionQueryHelper::escape($root),
    +            EntityDefinitionQueryHelper::escape($field->getStorageName()),
                 (string) $this->connection->quote('$' . $jsonPath)
             );
     
    @@ -76,6 +76,9 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
             return sprintf('IF(JSON_TYPE(%s) != "NULL", %s, NULL)', $jsonValueExpr, $accessor);
         }
     
    +    /**
    +     * @param Field[] $fields
    +     */
         private function getField(string $path, array $fields): ?Field
         {
             /** @var string $fieldName */
    
  • src/Core/Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/PriceFieldAccessorBuilder.php+6 5 modified
    @@ -6,6 +6,7 @@
     use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
     use Shopware\Core\Defaults;
     use Shopware\Core\Framework\Context;
    +use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
     use Shopware\Core\Framework\DataAbstractionLayer\Field\Field;
     use Shopware\Core\Framework\DataAbstractionLayer\Field\PriceField;
     use Shopware\Core\Framework\Log\Package;
    @@ -74,11 +75,11 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
              * We can indirectly cast to float by adding 0.0
              */
     
    -        $template = '(JSON_UNQUOTE(JSON_EXTRACT(`#root#`.`#field#`, "$.c#currencyId#.#property#")) #factor#)';
    +        $template = '(JSON_UNQUOTE(JSON_EXTRACT(#root#.#field#, "$.c#currencyId#.#property#")) #factor#)';
     
             $variables = [
    -            '#root#' => $root,
    -            '#field#' => $field->getStorageName(),
    +            '#root#' => EntityDefinitionQueryHelper::escape($root),
    +            '#field#' => EntityDefinitionQueryHelper::escape($field->getStorageName()),
                 '#currencyId#' => $currencyId,
                 '#property#' => $jsonAccessor,
                 '#factor#' => '+ 0.0',
    @@ -88,8 +89,8 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
     
             if ($currencyId !== Defaults::CURRENCY) {
                 $variables = [
    -                '#root#' => $root,
    -                '#field#' => $field->getStorageName(),
    +                '#root#' => EntityDefinitionQueryHelper::escape($root),
    +                '#field#' => EntityDefinitionQueryHelper::escape($field->getStorageName()),
                     '#currencyId#' => Defaults::CURRENCY,
                     '#property#' => $jsonAccessor,
                     '#factor#' => $currencyFactor,
    
  • src/Core/Framework/Test/DataAbstractionLayer/Search/EntityAggregatorTest.php+12 0 modified
    @@ -1328,6 +1328,18 @@ public function testAggregateNonExistingShouldFail(): void
             $this->aggregator->aggregate($this->getContainer()->get(TaxDefinition::class), $criteria, $context);
         }
     
    +    public function testAggregationWithBacktickInName(): void
    +    {
    +        $context = Context::createDefaultContext();
    +
    +        $criteria = new Criteria();
    +        $criteria->addAggregation(new SumAggregation('`taxRate`', 'taxRate'));
    +
    +        static::expectException(\InvalidArgumentException::class);
    +        static::expectExceptionMessage('Backtick not allowed in identifier');
    +        $this->aggregator->aggregate($this->getContainer()->get(TaxDefinition::class), $criteria, $context);
    +    }
    +
         private function insertData(): void
         {
             $repository = $this->getContainer()->get('product.repository');
    
e2256ec81e56

NEXT-32887 - Improve SQL escaping in DAL

https://github.com/shopware/coreSoner SayakciJan 3, 2024via ghsa
4 files changed · +39 23
  • Framework/DataAbstractionLayer/Dbal/EntityAggregator.php+15 15 modified
    @@ -293,11 +293,11 @@ private function parseDateHistogramAggregation(
             $query->addGroupBy($groupBy);
     
             $key = $aggregation->getName() . '.key';
    -        $query->addSelect(sprintf('MIN(%s) as `%s`', $accessor, $key));
    +        $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($key)));
     
             $key = $aggregation->getName() . '.count';
             $countAccessor = $this->queryHelper->getFieldAccessor('id', $definition, $definition->getEntityName(), $context);
    -        $query->addSelect(sprintf('COUNT(%s) as `%s`', $countAccessor, $key));
    +        $query->addSelect(sprintf('COUNT(%s) as %s', $countAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             if ($aggregation->getSorting()) {
                 $this->addSorting($aggregation->getSorting(), $definition, $query, $context);
    @@ -326,12 +326,12 @@ private function parseTermsAggregation(
                 $keyAccessor = 'LOWER(HEX(' . $keyAccessor . '))';
             }
     
    -        $query->addSelect(sprintf('%s as `%s`', $keyAccessor, $key));
    +        $query->addSelect(sprintf('%s as %s', $keyAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             $key = $aggregation->getName() . '.count';
     
             $countAccessor = $this->queryHelper->getFieldAccessor('id', $definition, $definition->getEntityName(), $context);
    -        $query->addSelect(sprintf('COUNT(%s) as `%s`', $countAccessor, $key));
    +        $query->addSelect(sprintf('COUNT(%s) as %s', $countAccessor, EntityDefinitionQueryHelper::escape($key)));
     
             if ($aggregation->getLimit()) {
                 $query->setMaxResults($aggregation->getLimit());
    @@ -354,7 +354,7 @@ private function parseAvgAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('AVG(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('AVG(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseSumAggregation(
    @@ -365,7 +365,7 @@ private function parseSumAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('SUM(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('SUM(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseMaxAggregation(
    @@ -376,7 +376,7 @@ private function parseMaxAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('MAX(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('MAX(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseMinAggregation(
    @@ -387,7 +387,7 @@ private function parseMinAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('MIN(%s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseCountAggregation(
    @@ -398,7 +398,7 @@ private function parseCountAggregation(
         ): void {
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
    -        $query->addSelect(sprintf('COUNT(DISTINCT %s) as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('COUNT(DISTINCT %s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         private function parseStatsAggregation(
    @@ -410,16 +410,16 @@ private function parseStatsAggregation(
             $accessor = $this->queryHelper->getFieldAccessor($aggregation->getField(), $definition, $definition->getEntityName(), $context);
     
             if ($aggregation->fetchAvg()) {
    -            $query->addSelect(sprintf('AVG(%s) as `%s.avg`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('AVG(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.avg')));
             }
             if ($aggregation->fetchMin()) {
    -            $query->addSelect(sprintf('MIN(%s) as `%s.min`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('MIN(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.min')));
             }
             if ($aggregation->fetchMax()) {
    -            $query->addSelect(sprintf('MAX(%s) as `%s.max`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('MAX(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.max')));
             }
             if ($aggregation->fetchSum()) {
    -            $query->addSelect(sprintf('SUM(%s) as `%s.sum`', $accessor, $aggregation->getName()));
    +            $query->addSelect(sprintf('SUM(%s) as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.sum')));
             }
         }
     
    @@ -445,7 +445,7 @@ private function parseRangeAggregation(
                     $sum .= sprintf(' AND %s < %f', $accessor, $range['to']);
                 }
     
    -            $query->addSelect(sprintf('SUM(%s) as `%s.%s`', $sum, $aggregation->getName(), $id));
    +            $query->addSelect(sprintf('SUM(%s) as %s', $sum, EntityDefinitionQueryHelper::escape($aggregation->getName() . '.' . $id)));
             }
         }
     
    @@ -459,7 +459,7 @@ private function parseEntityAggregation(
             $query->addGroupBy($accessor);
     
             $accessor = 'LOWER(HEX(' . $accessor . '))';
    -        $query->addSelect(sprintf('%s as `%s`', $accessor, $aggregation->getName()));
    +        $query->addSelect(sprintf('%s as %s', $accessor, EntityDefinitionQueryHelper::escape($aggregation->getName())));
         }
     
         /**
    
  • Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/JsonFieldAccessorBuilder.php+6 3 modified
    @@ -58,9 +58,9 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
             }
     
             $jsonValueExpr = sprintf(
    -            'JSON_EXTRACT(`%s`.`%s`, %s)',
    -            $root,
    -            $field->getStorageName(),
    +            'JSON_EXTRACT(%s.%s, %s)',
    +            EntityDefinitionQueryHelper::escape($root),
    +            EntityDefinitionQueryHelper::escape($field->getStorageName()),
                 (string) $this->connection->quote('$' . $jsonPath)
             );
     
    @@ -76,6 +76,9 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
             return sprintf('IF(JSON_TYPE(%s) != "NULL", %s, NULL)', $jsonValueExpr, $accessor);
         }
     
    +    /**
    +     * @param Field[] $fields
    +     */
         private function getField(string $path, array $fields): ?Field
         {
             /** @var string $fieldName */
    
  • Framework/DataAbstractionLayer/Dbal/FieldAccessorBuilder/PriceFieldAccessorBuilder.php+6 5 modified
    @@ -6,6 +6,7 @@
     use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
     use Shopware\Core\Defaults;
     use Shopware\Core\Framework\Context;
    +use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
     use Shopware\Core\Framework\DataAbstractionLayer\Field\Field;
     use Shopware\Core\Framework\DataAbstractionLayer\Field\PriceField;
     use Shopware\Core\Framework\Log\Package;
    @@ -74,11 +75,11 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
              * We can indirectly cast to float by adding 0.0
              */
     
    -        $template = '(JSON_UNQUOTE(JSON_EXTRACT(`#root#`.`#field#`, "$.c#currencyId#.#property#")) #factor#)';
    +        $template = '(JSON_UNQUOTE(JSON_EXTRACT(#root#.#field#, "$.c#currencyId#.#property#")) #factor#)';
     
             $variables = [
    -            '#root#' => $root,
    -            '#field#' => $field->getStorageName(),
    +            '#root#' => EntityDefinitionQueryHelper::escape($root),
    +            '#field#' => EntityDefinitionQueryHelper::escape($field->getStorageName()),
                 '#currencyId#' => $currencyId,
                 '#property#' => $jsonAccessor,
                 '#factor#' => '+ 0.0',
    @@ -88,8 +89,8 @@ public function buildAccessor(string $root, Field $field, Context $context, stri
     
             if ($currencyId !== Defaults::CURRENCY) {
                 $variables = [
    -                '#root#' => $root,
    -                '#field#' => $field->getStorageName(),
    +                '#root#' => EntityDefinitionQueryHelper::escape($root),
    +                '#field#' => EntityDefinitionQueryHelper::escape($field->getStorageName()),
                     '#currencyId#' => Defaults::CURRENCY,
                     '#property#' => $jsonAccessor,
                     '#factor#' => $currencyFactor,
    
  • Framework/Test/DataAbstractionLayer/Search/EntityAggregatorTest.php+12 0 modified
    @@ -1328,6 +1328,18 @@ public function testAggregateNonExistingShouldFail(): void
             $this->aggregator->aggregate($this->getContainer()->get(TaxDefinition::class), $criteria, $context);
         }
     
    +    public function testAggregationWithBacktickInName(): void
    +    {
    +        $context = Context::createDefaultContext();
    +
    +        $criteria = new Criteria();
    +        $criteria->addAggregation(new SumAggregation('`taxRate`', 'taxRate'));
    +
    +        static::expectException(\InvalidArgumentException::class);
    +        static::expectExceptionMessage('Backtick not allowed in identifier');
    +        $this->aggregator->aggregate($this->getContainer()->get(TaxDefinition::class), $criteria, $context);
    +    }
    +
         private function insertData(): void
         {
             $repository = $this->getContainer()->get('product.repository');
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.