-
-
Notifications
You must be signed in to change notification settings - Fork 857
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request from GHSA-vr2x-7687-h6qv
- Loading branch information
Showing
8 changed files
with
67 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,68 +19,68 @@ | |
use ApiPlatform\JsonLd\ContextBuilderInterface; | ||
use ApiPlatform\JsonLd\Serializer\JsonLdContextTrait; | ||
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; | ||
use ApiPlatform\Serializer\ContextTrait; | ||
use ApiPlatform\Serializer\AbstractCollectionNormalizer; | ||
use ApiPlatform\State\Pagination\PaginatorInterface; | ||
use ApiPlatform\State\Pagination\PartialPaginatorInterface; | ||
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; | ||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; | ||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; | ||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface; | ||
use Symfony\Component\Serializer\Serializer; | ||
|
||
/** | ||
* This normalizer handles collections. | ||
* | ||
* @author Kevin Dunglas <[email protected]> | ||
* @author Samuel ROZE <[email protected]> | ||
*/ | ||
final class CollectionNormalizer implements NormalizerInterface, NormalizerAwareInterface, CacheableSupportsMethodInterface | ||
final class CollectionNormalizer extends AbstractCollectionNormalizer | ||
{ | ||
use ContextTrait; | ||
use JsonLdContextTrait; | ||
use NormalizerAwareTrait; | ||
|
||
public const FORMAT = 'jsonld'; | ||
public const IRI_ONLY = 'iri_only'; | ||
private array $defaultContext = [ | ||
self::IRI_ONLY => false, | ||
]; | ||
|
||
public function __construct(private readonly ContextBuilderInterface $contextBuilder, private readonly ResourceClassResolverInterface $resourceClassResolver, private readonly IriConverterInterface $iriConverter, private readonly ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, array $defaultContext = []) | ||
public function __construct(private readonly ContextBuilderInterface $contextBuilder, ResourceClassResolverInterface $resourceClassResolver, private readonly IriConverterInterface $iriConverter, private readonly ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, array $defaultContext = []) | ||
{ | ||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext); | ||
|
||
if ($this->resourceMetadataCollectionFactory) { | ||
trigger_deprecation('api-platform/core', '3.0', sprintf('Injecting "%s" within "%s" is not needed anymore and this dependency will be removed in 4.0.', ResourceMetadataCollectionFactoryInterface::class, self::class)); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool | ||
{ | ||
return self::FORMAT === $format && is_iterable($data); | ||
parent::__construct($resourceClassResolver, ''); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @param iterable $object | ||
* Gets the pagination data. | ||
*/ | ||
public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null | ||
protected function getPaginationData(iterable $object, array $context = []): array | ||
{ | ||
if (!isset($context['resource_class']) || isset($context['api_sub_level'])) { | ||
return $this->normalizeRawCollection($object, $format, $context); | ||
} | ||
|
||
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class']); | ||
$context = $this->initContext($resourceClass, $context); | ||
$context['api_collection_sub_level'] = true; | ||
$data = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); | ||
$data['@id'] = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); | ||
$data['@type'] = 'hydra:Collection'; | ||
|
||
if ($object instanceof PaginatorInterface) { | ||
$data['hydra:totalItems'] = $object->getTotalItems(); | ||
} | ||
|
||
if (\is_array($object) || ($object instanceof \Countable && !$object instanceof PartialPaginatorInterface)) { | ||
$data['hydra:totalItems'] = \count($object); | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
/** | ||
* Gets items data. | ||
*/ | ||
protected function getItemsData(iterable $object, string $format = null, array $context = []): array | ||
{ | ||
$data = []; | ||
$data['hydra:member'] = []; | ||
|
||
$iriOnly = $context[self::IRI_ONLY] ?? $this->defaultContext[self::IRI_ONLY]; | ||
|
||
if (($operation = $context['operation'] ?? null) && method_exists($operation, 'getItemUriTemplate')) { | ||
|
@@ -108,36 +108,6 @@ public function normalize(mixed $object, string $format = null, array $context = | |
} | ||
} | ||
|
||
if ($object instanceof PaginatorInterface) { | ||
$data['hydra:totalItems'] = $object->getTotalItems(); | ||
} | ||
|
||
if (\is_array($object) || ($object instanceof \Countable && !$object instanceof PartialPaginatorInterface)) { | ||
$data['hydra:totalItems'] = \count($object); | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
public function hasCacheableSupportsMethod(): bool | ||
{ | ||
return true; | ||
} | ||
|
||
/** | ||
* Normalizes a raw collection (not API resources). | ||
*/ | ||
protected function normalizeRawCollection(iterable $object, string $format = null, array $context = []): array|\ArrayObject | ||
{ | ||
if (\is_array($object) && !$object && ($context[Serializer::EMPTY_ARRAY_AS_OBJECT] ?? false)) { | ||
return new \ArrayObject(); | ||
} | ||
|
||
$data = []; | ||
foreach ($object as $index => $obj) { | ||
$data[$index] = $this->normalizer->normalize($obj, $format, $context); | ||
} | ||
|
||
return $data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Toflar @soyuka does this affect only API Platform 2.7.0 and newer?
Because the version range at GHSA-vr2x-7687-h6qv (which says < 2.7.10) may produce false positives since this would theoretically include all versions down to 1.0 / the first version.
Also this line says, that only specific branches are affected:
https://github.com/api-platform/core/blob/main/CHANGELOG.md#270-alpha1
https://github.com/api-platform/core/releases/tag/v2.7.0
Unfortunately there is no good overview in the documentation, in which version some feature was added:
https://api-platform.com/docs/core/security/
https://api-platform.com/docs/schema-generator/configuration/#adding-a-custom-attribute-or-modifying-a-generated-attribute
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to speak for @soyuka or any APIP maintainer so you might want to wait for an official response.
But here's my reasoning: I think < 2.7.10 was used because this is the lowest version currently still being maintained. In other words, nobody cares about the exact lower versions that are affected as these are all unmaintained anyway and might even contain other security vulnerabilites. If you care about your API being protected, you need to update to a maintained version anway :) So why even bother?
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Toflar because in this case here GitHub as CNA (CVE Numbering Authority) would also set the CPE (Common Platform Enumeration) value to < 2.7.10 so every security scanner would wrongly report this CVE in older versions. Which is basically a false positive. Many do no full research and then have a problem because such false positives lead to wrong assumptions.
A lower end for the ranges (and a correct CPE) is always recommended so security scanners can properly detect and flag this.
It's more about correct CVE identification. Also regarding unmaintained / outdated versions: in most cases you can tell (by checking the technical details) if a project is really affected by something or if a CVE is mitigated (by design) / poses no actual risk.
Unfortunately it is not the first case that wrong CPE entries derived from GitHub Advisories cause false positives and thus lead to other problems (due to the wrong information).
If we want to do it the right way, then we need exact and correct version ranges with lower limits.
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look, the situation presents itself rather straight-forward:
A lower bound is only helpful, if it's precisely the version where a vulnerability was introduced. Otherwise, you would potentially report a given version range as being safe even though it isn't. These false-positives would be much worse than what we have now.
And in order to find out which version was the one introducing the vulnerability, you have two options:
a) either you know exactly
b) or you have to find out
I guess we can safely assume that a) was not the case here, otherwise the lower bound would've been set accordingly.
So we're left with b).
Finding out would mean you have to go back in time and write tests for all those lower versions. The tests might even need to be different in 2.6, 2.5, 2.4 etc. because the code changed, CI changed, tools used changed etc.
It needs a lot of time. Time that people usually are not ready to invest in unmaintained software.
That being said, I'm fairly sure that the report would be adjusted if you want to be the one doing that investigation to find out the precise lower bound.
Anyway, I won't be adding anything else to this discussion. I'm not arguing against the proper lower bound. You asked for a reason and I tried to give you a potential answer to your question because you mentioned me :) As I said, you may want to wait for a response from a maintainer. I can't change anything about it anyway.
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @DanielRuf,
Our reasoning is that, even if this issue was introduced in 2.7 (which we aren't sure at 100% as it also depends on the version of some of your vendors), we don't want people to stay on non-maintained versions. It is okay if this issue gets detected on < 2.7.0. Today, it is really hard to try and find exactly when this was introduced as you'd have to also take into consideration the matrix of symfony dependencies this bug relates to. With PHP 7.x not being supported anymore (security-wise) it is a security issue to be on < 2.7. Indeed, 2.7 is the minimal version to have security updates on this project.
Anyways, the feature for security attributes was introduced at 6e3a259 so I can add the > 2.6 constraint if you think it's better?
/edit: boundary for 2.6 added.
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much. Let's see then if GitHub as CNA updates the CPE entries.
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@soyuka one last small question: shouldn't it be
>= 2.6.0
as this includes 2.6.0?6e3a259
https://github.com/api-platform/core/releases/tag/v2.6.0
dcc4733
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DanielRuf fixed thanks