Skip to content

fix(symfony): don't expose entrypoint in openapi format#8383

Merged
soyuka merged 1 commit into
api-platform:4.3from
soyuka:fix/8361-entrypoint-openapi-format-leak
Jul 3, 2026
Merged

fix(symfony): don't expose entrypoint in openapi format#8383
soyuka merged 1 commit into
api-platform:4.3from
soyuka:fix/8361-entrypoint-openapi-format-leak

Conversation

@soyuka

@soyuka soyuka commented Jul 3, 2026

Copy link
Copy Markdown
Member

Fixes #8361

Bug

Requesting the API entrypoint in an OpenAPI/documentation format returned 200 OK with a JSON dump of the internal resourceNameCollection, leaking every registered resource's PHP FQCN:

GET / — Accept: application/vnd.openapi+json

{"resourceNameCollection":["ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy", ...]}

Root cause

EntrypointAction builds its Get operation with outputFormats: %api_platform.docs_formats%, which includes jsonopenapi, yamlopenapi, json and html. There is no EntrypointNormalizer for the OpenAPI formats — only jsonld, jsonhal and jsonapi have one (plus a dedicated Swagger UI code path for html). Content negotiation therefore accepted application/vnd.openapi+json, and with no matching normalizer the Symfony ObjectNormalizer fallback serialized the public Entrypoint::$resourceNameCollection property, leaking the class names.

Fix

Introduce a new api_platform.entrypoint_formats parameter — the intersection of docs_formats with the formats the entrypoint can actually render (jsonld, jsonhal, jsonapi, html) — and inject it into the entrypoint action instead of docs_formats, in both the controller and event-listener service definitions. Documentation formats now yield:

  • 406 Not Acceptable when requested via Accept header (e.g. Accept: application/vnd.openapi+json on /)
  • 404 Not Found when requested via URL suffix (e.g. /index.jsonopenapi), consistent with any other resource requested with an unsupported route-format suffix (routing resolves _format before content negotiation runs)

All hypermedia formats keep working, and html still serves the Swagger UI.

The enable_entrypoint default is intentionally not changed — this keeps the current BC posture; only the format set exposed by the entrypoint is constrained.

Tests

  • New tests/Functional/EntrypointFormatTest.php: asserts 406 for the OpenAPI Accept header, 404 for the .jsonopenapi/.yamlopenapi URL suffixes, and that jsonld/jsonhal/jsonapi still return 200 with proper IRIs (and no resourceNameCollection leak), plus html still renders Swagger UI.
  • Updated the two OpenApiTest cases that previously encoded the leak as an expected 200.

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
@soyuka soyuka force-pushed the fix/8361-entrypoint-openapi-format-leak branch from e7eedee to 16f4f9a Compare July 3, 2026 05:51
@soyuka soyuka merged commit 328cb67 into api-platform:4.3 Jul 3, 2026
111 of 112 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant