{"id":"GHSA-9rjg-x2p2-h68h","summary":"API Platform Core: Relation IRIs are not type-checked: a related resource can be denormalised as the wrong resource type (type confusion)","details":"## Summary\n\nThe API Platform serializer's `AbstractItemNormalizer` does not validate the resource type returned when resolving relation IRIs, allowing type confusion where a resource of an unintended type can be silently assigned to a relation property.\n\n## Impact\n\nAn attacker who can submit write requests (POST/PUT/PATCH) to an API Platform endpoint with writable relations can supply a relation IRI pointing to a resource of a different type than the relation's declared class. Because `getResourceFromIri()` does not pass an `$operation` to `IriConverter::getResourceFromIri()`, the `is_a` type guard at `IriConverter.php:86` is skipped. For untyped relation properties (legacy `@var`-only style), the wrong-typed object is silently assigned, corrupting invariants and potentially feeding downstream logic that assumes the declared type (CWE-843). For typed properties (modern PHP 8.x), the substitution is blocked by Symfony's PropertyAccessor with an `InvalidTypeException`.\n\n## Affected versions\n\n- `api-platform/core` `\u003c 4.1.30`\n- `api-platform/core` `\u003e= 4.2.0, \u003c 4.2.26`\n- `api-platform/core` `\u003e= 4.3.0, \u003c 4.3.12`\n\nOlder major series (`2.x`, `3.x`) ship the same vulnerable code path and are end-of-life; no fix is planned.\n\n## Patched versions\n\n- `4.1.30`\n- `4.2.26`\n- `4.3.12`\n\n## Fix\n\nAn `is_a` guard is added inside `AbstractItemNormalizer::getResourceFromIri()` (and the equivalent inline call sites on 4.1) so that a mismatched IRI throws `InvalidArgumentException`, mirroring the operation-aware check the `IriConverter` already performs when an operation is supplied. This forces a `400 Bad Request` response for cross-type IRIs instead of a silent assignment.\n\n## Workarounds\n\nDeclare a PHP type on every writable relation property (e.g. `public ?Foo $relation = null;` instead of `@var Foo $relation`). Symfony's `PropertyAccessor` will then reject a mismatched object with `InvalidTypeException`. This does not cover collections of mixed-type interfaces; upgrading to a patched version is the only complete fix.\n\n## Proof of concept\n\nA functional test posts a `Bar` IRI to a `Foo`-declared relation on an untyped property. Without the fix the server responds with `HTTP 201` and the Bar IRI appears in the response payload. With the fix the server responds with `HTTP 400` (`Invalid IRI \"/bars/1\"`).\n\nFull PoC: `tests/Functional/Security/TypeConfusionRelationIriTest.php` in the patched branches.\n\n## References\n\n- `src/Serializer/AbstractItemNormalizer.php` — vulnerable relation IRI load\n- `src/Symfony/Routing/IriConverter.php` — conditional `is_a` guard (operation-aware path)\n\n## Credit\n\nReported by @alexandre-daubois.","aliases":["CVE-2026-54164"],"modified":"2026-08-07T17:00:23.583676514Z","published":"2026-08-07T16:54:42Z","database_specific":{"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-08-07T16:54:42Z","nvd_published_at":"2026-07-01T20:17:10Z","cwe_ids":["CWE-843"]},"references":[{"type":"WEB","url":"https://github.com/api-platform/core/security/advisories/GHSA-9rjg-x2p2-h68h"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54164"},{"type":"WEB","url":"https://github.com/api-platform/core/commit/6bcbeb2dbee53db5bb9b4b8e343bffdf7732de1e"},{"type":"PACKAGE","url":"https://github.com/api-platform/core"},{"type":"WEB","url":"https://github.com/api-platform/core/releases/tag/v4.1.30"},{"type":"WEB","url":"https://github.com/api-platform/core/releases/tag/v4.2.26"},{"type":"WEB","url":"https://github.com/api-platform/core/releases/tag/v4.3.12"}],"affected":[{"package":{"name":"api-platform/core","ecosystem":"Packagist","purl":"pkg:composer/api-platform/core"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.1.30"}]}],"versions":["4.1.14","v1.0.0","v1.0.0-beta","v1.0.0-beta.2","v1.0.0-beta.3","v1.0.1","v1.1.0","v1.1.0-beta.1","v1.1.0-beta.2","v1.1.1","v2.0.0","v2.0.0-alpha.1","v2.0.0-alpha.2","v2.0.0-beta.1","v2.0.0-beta.2","v2.0.0-beta.3","v2.0.0-rc.1","v2.0.0-rc.2","v2.0.0-rc.3","v2.0.0-rc.4","v2.0.0-rc.5","v2.0.0-rc.6","v2.0.1","v2.0.10","v2.0.11","v2.0.2","v2.0.3","v2.0.4","v2.0.5","v2.0.6","v2.0.7","v2.0.8","v2.0.9","v2.1.0","v2.1.0-beta.1","v2.1.0-beta.2","v2.1.1","v2.1.2","v2.1.3","v2.1.4","v2.1.5","v2.1.6","v2.2.0","v2.2.0-beta.1","v2.2.0-beta.2","v2.2.1","v2.2.10","v2.2.2","v2.2.3","v2.2.4","v2.2.5","v2.2.6","v2.2.7","v2.2.8","v2.2.9","v2.3.0","v2.3.0-beta.1","v2.3.1","v2.3.2","v2.3.3","v2.3.4","v2.3.5","v2.3.6","v2.4.0","v2.4.0-beta.1","v2.4.0-beta.2","v2.4.1","v2.4.2","v2.4.3","v2.4.4","v2.4.5","v2.4.6","v2.4.7","v2.5.0","v2.5.0-beta.1","v2.5.0-beta.2","v2.5.1","v2.5.10","v2.5.2","v2.5.3","v2.5.4","v2.5.5","v2.5.6","v2.5.7","v2.5.8","v2.5.9","v2.6.0","v2.6.0-alpha.1","v2.6.0-beta.1","v2.6.1","v2.6.2","v2.6.3","v2.6.3-alpha.1","v2.6.3.alpha","v2.6.4","v2.6.5","v2.6.6","v2.6.7","v2.6.8","v2.7.0","v2.7.0-alpha.1","v2.7.0-alpha.2","v2.7.0-alpha.3","v2.7.0-alpha.4","v2.7.0-alpha.5","v2.7.0-alpha.6","v2.7.0-alpha.7","v2.7.0-beta.1","v2.7.0-beta.2","v2.7.0-beta.3","v2.7.0-beta.4","v2.7.0-beta.5","v2.7.0-rc.1","v2.7.0-rc.2","v2.7.1","v2.7.10","v2.7.11","v2.7.12","v2.7.13","v2.7.14","v2.7.15","v2.7.16","v2.7.17","v2.7.18","v2.7.2","v2.7.3","v2.7.4","v2.7.5","v2.7.6","v2.7.7","v2.7.8","v2.7.9","v3.0.0","v3.0.0-beta.1","v3.0.0-beta.2","v3.0.0-rc.1","v3.0.0-rc.2","v3.0.1","v3.0.10","v3.0.11","v3.0.12","v3.0.2","v3.0.3","v3.0.4","v3.0.5","v3.0.6","v3.0.7","v3.0.8","v3.0.9","v3.1.0","v3.1.1","v3.1.10","v3.1.11","v3.1.12","v3.1.13","v3.1.14","v3.1.15","v3.1.16","v3.1.17","v3.1.18","v3.1.19","v3.1.2","v3.1.20","v3.1.21","v3.1.22","v3.1.23","v3.1.24","v3.1.25","v3.1.26","v3.1.27","v3.1.28","v3.1.29","v3.1.3","v3.1.4","v3.1.5","v3.1.6","v3.1.7","v3.1.8","v3.1.9","v3.2.0","v3.2.0-alpha.1","v3.2.0-alpha.2","v3.2.0-beta.1","v3.2.0-beta.2","v3.2.1","v3.2.10","v3.2.11","v3.2.12","v3.2.13","v3.2.14","v3.2.15","v3.2.16","v3.2.17","v3.2.18","v3.2.19","v3.2.2","v3.2.20","v3.2.21","v3.2.22","v3.2.23","v3.2.24","v3.2.25","v3.2.26","v3.2.3","v3.2.4","v3.2.5","v3.2.6","v3.2.7","v3.2.8","v3.2.9","v3.3.0","v3.3.0-alpha.1","v3.3.0-alpha.2","v3.3.0-beta.1","v3.3.0-beta.2","v3.3.1","v3.3.10","v3.3.11","v3.3.12","v3.3.13","v3.3.14","v3.3.15","v3.3.2","v3.3.3","v3.3.4","v3.3.5","v3.3.6","v3.3.7","v3.3.8","v3.3.9","v3.4.0","v3.4.0-alpha.1","v3.4.0-alpha.2","v3.4.0-alpha.3","v3.4.0-alpha.4","v3.4.0-alpha.5","v3.4.0-alpha.6","v3.4.0-alpha.7","v3.4.0-beta.1","v3.4.1","v3.4.10","v3.4.11","v3.4.14","v3.4.15","v3.4.16","v3.4.17","v3.4.2","v3.4.3","v3.4.4","v3.4.5","v3.4.6","v3.4.7","v3.4.8","v3.4.9","v4.0.0","v4.0.0-alpha.1","v4.0.0-alpha.2","v4.0.0-alpha.3","v4.0.0-alpha.4","v4.0.0-alpha.5","v4.0.0-alpha.6","v4.0.0-alpha.7","v4.0.0-beta.1","v4.0.0-beta.2","v4.0.1","v4.0.10","v4.0.11","v4.0.12","v4.0.13","v4.0.14","v4.0.15","v4.0.16","v4.0.17","v4.0.18","v4.0.19","v4.0.2","v4.0.20","v4.0.21","v4.0.22","v4.0.3","v4.0.4","v4.0.5","v4.0.6","v4.0.7","v4.0.8","v4.0.9","v4.1.0","v4.1.0-alpha.1","v4.1.0-alpha.2","v4.1.0-beta.1","v4.1.0-beta.2","v4.1.1","v4.1.10","v4.1.11","v4.1.12","v4.1.15","v4.1.16","v4.1.17","v4.1.18","v4.1.19","v4.1.2","v4.1.20","v4.1.21","v4.1.22","v4.1.23","v4.1.24","v4.1.25","v4.1.26","v4.1.27","v4.1.28","v4.1.29","v4.1.3","v4.1.4","v4.1.5","v4.1.6","v4.1.7","v4.1.8","v4.1.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-9rjg-x2p2-h68h/GHSA-9rjg-x2p2-h68h.json"}},{"package":{"name":"api-platform/core","ecosystem":"Packagist","purl":"pkg:composer/api-platform/core"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.2.0"},{"fixed":"4.2.26"}]}],"versions":["v4.2.0","v4.2.1","v4.2.10","v4.2.11","v4.2.12","v4.2.13","v4.2.14","v4.2.15","v4.2.16","v4.2.17","v4.2.18","v4.2.19","v4.2.2","v4.2.20","v4.2.21","v4.2.22","v4.2.23","v4.2.24","v4.2.25","v4.2.3","v4.2.4","v4.2.5","v4.2.6","v4.2.7","v4.2.8","v4.2.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-9rjg-x2p2-h68h/GHSA-9rjg-x2p2-h68h.json"}},{"package":{"name":"api-platform/core","ecosystem":"Packagist","purl":"pkg:composer/api-platform/core"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.3.0"},{"fixed":"4.3.12"}]}],"versions":["v4.3.0","v4.3.1","v4.3.10","v4.3.11","v4.3.2","v4.3.3","v4.3.4","v4.3.5","v4.3.6","v4.3.7","v4.3.8","v4.3.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-9rjg-x2p2-h68h/GHSA-9rjg-x2p2-h68h.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N"}]}