Packagist · api-platform/core
API Platform Core vulnerable to cross-user attribute leak in JSON:API and HAL item normalizers due to missing isCacheKeySafe gate
#[ApiProperty(security: ...)] is evaluated per request to decide whether a property is exposed. The componentsCache arrays in ApiPlatform\JsonApi\Serializer\ItemNormalizer and ApiPlatform\Hal\Serializer\ItemNormalizer are keyed on $context['cache_key'], which is set unconditionally before delegating to the parent normalizer. The component structure (attributes, relationships, links) computed for one request can therefore be reused for a subsequent request whose user has a different set of accessible properties. A user with lower privileges may end up seeing the structure of properties that the security predicate would otherwise have hidden for them.
This is the same vulnerability class as GHSA-428q-q3vv-3fq3 / CVE-2025-31485, which fixed only the GraphQL ItemNormalizer. The JSON:API and HAL paths were not addressed at the time.
Exploitation requires all of the following to coincide:
#[ApiProperty(security: ...)] with a predicate whose result depends on the current user (or on per-request state).true populates componentsCache before a request from a user for whom the predicate evaluates to false, within the lifetime of the same PHP process.php-fpm workers the cache only survives the duration of a single request, which makes the issue much harder to observe in practice.All three branches receive patched releases of api-platform/core, api-platform/json-api, and api-platform/hal.
Override the JSON:API and HAL ItemNormalizer services to gate $context['cache_key'] with a resource-class security check, or avoid #[ApiProperty(security: ...)] on resources served as JSON:API or HAL until the patch is applied. Pinning the deployment to classic php-fpm workers also limits exposure since the cache does not survive across requests.
isCacheKeySafe to AbstractItemNormalizer.Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.
Check my repoSources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.