fix(symfony): don't expose entrypoint in openapi format#8383
Merged
soyuka merged 1 commit intoJul 3, 2026
Conversation
The entrypoint's Get operation used %api_platform.docs_formats% for its outputFormats, which includes openapi/yamlopenapi. No EntrypointNormalizer exists for those formats (only jsonld, jsonhal and jsonapi have one, plus a dedicated Swagger UI code path for html), so content negotiation let the format through and the Symfony ObjectNormalizer fallback serialized the public ResourceNameCollection property, leaking internal PHP FQCNs. Introduce an api_platform.entrypoint_formats parameter, the intersection of docs_formats with the formats the entrypoint actually knows how to render (jsonld, jsonhal, jsonapi, html), and use it instead of docs_formats for the entrypoint action in both the controller and event-listener service definitions. Documentation formats now correctly yield a 404 (unsupported route format suffix, e.g. /index.jsonopenapi) or 406 (unsupported Accept header) instead of a 200 with leaked class names. enable_entrypoint default is intentionally left unchanged. Also guard ContentNegotiationTrait::getRequestFormat() against a null mime type: an unknown route _format suffix (e.g. jsonopenapi) makes Request::getMimeType() return null, which triggered a PHP 8.5 "null as array offset" deprecation and would have thrown a TypeError on the $throw path. Fixes api-platform#8361
e7eedee to
16f4f9a
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8361
Bug
Requesting the API entrypoint in an OpenAPI/documentation format returned
200 OKwith a JSON dump of the internalresourceNameCollection, leaking every registered resource's PHP FQCN:Root cause
EntrypointActionbuilds itsGetoperation withoutputFormats: %api_platform.docs_formats%, which includesjsonopenapi,yamlopenapi,jsonandhtml. There is noEntrypointNormalizerfor the OpenAPI formats — onlyjsonld,jsonhalandjsonapihave one (plus a dedicated Swagger UI code path forhtml). Content negotiation therefore acceptedapplication/vnd.openapi+json, and with no matching normalizer the SymfonyObjectNormalizerfallback serialized the publicEntrypoint::$resourceNameCollectionproperty, leaking the class names.Fix
Introduce a new
api_platform.entrypoint_formatsparameter — the intersection ofdocs_formatswith the formats the entrypoint can actually render (jsonld,jsonhal,jsonapi,html) — and inject it into the entrypoint action instead ofdocs_formats, in both the controller and event-listener service definitions. Documentation formats now yield:406 Not Acceptablewhen requested viaAcceptheader (e.g.Accept: application/vnd.openapi+jsonon/)404 Not Foundwhen requested via URL suffix (e.g./index.jsonopenapi), consistent with any other resource requested with an unsupported route-format suffix (routing resolves_formatbefore content negotiation runs)All hypermedia formats keep working, and
htmlstill serves the Swagger UI.The
enable_entrypointdefault is intentionally not changed — this keeps the current BC posture; only the format set exposed by the entrypoint is constrained.Tests
tests/Functional/EntrypointFormatTest.php: asserts 406 for the OpenAPIAcceptheader, 404 for the.jsonopenapi/.yamlopenapiURL suffixes, and thatjsonld/jsonhal/jsonapistill return 200 with proper IRIs (and noresourceNameCollectionleak), plushtmlstill renders Swagger UI.OpenApiTestcases that previously encoded the leak as an expected200.