JSON:API: request documents with no `data`, no `type` or a wrong `type` are accepted with 201
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 62/100
Línea de trabajo
Start in src/JsonApi/Serializer, where JsonApi\Serializer\ItemNormalizerTrait::denormalize() reads $data['data']['attributes'] ?? [] and $data['data']['relationships'] ?? [] without checking the document shape. Reproduce with the request bodies in the table (for example "Y", {"title":"A"} and a mismatched type) against a POST /novels operation. Done means malformed documents return 400 Bad Request, and a POST whose type does not match the endpoint returns 409 Conflict, with the existing JSON:API tests still passing.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
API Platform version(s) affected
4.4.4
Description
The JSON:API denormalizer does not check the structure of the request document. A body that is not a valid JSON:API document is accepted, and the resource is created with its default values.
The spec requires:
- the top level of a request document is an object with a
datamember (document structure), datais a resource object with atypemember, andattributesis an object (resource objects),- "A server MUST return
409 Conflictwhen processing aPOSTrequest in which the resource object'stypeis not among the type(s) that constitute the collection represented by the endpoint" (creating resources).
JsonApi\Serializer\ItemNormalizerTrait::denormalize() reads $data['data']['attributes'] ?? [] and $data['data']['relationships'] ?? [], and it does not check the other members.
How to reproduce
#[ApiResource(operations: [
new Get(provider: [self::class, 'provide']),
new Post(processor: [self::class, 'process']),
])]
final class Novel
{
public int $id = 1;
public string $title = 'Dune';
public static function provide(): self { return new self(); }
public static function process(self $data, Operation $operation): self { return $data; }
}
Each of these POST /novels bodies answers 201 Created:
| Body | Problem |
|---|---|
"Y" |
not an object |
42 |
not an object |
{"title":"A"} |
no data member |
{"data":"x"} |
data is not a resource object |
{"data":{"type":"Novel","attributes":["x"]}} |
attributes is not an object |
{"data":{"attributes":{"title":"A"}}} |
no type member |
{"data":{"type":"Author","attributes":{"title":"A"}}} |
type does not match the endpoint |
Response for "Y":
{"data":{"id":"/novels/1","type":"Novel","attributes":{"_id":1,"title":"Dune"}}}
A validation constraint on a required property hides the problem in some cases, but a resource with optional properties or defaults is created from any body.
Expected:
- A body that is not a JSON:API document, or has no
dataobject, notypeor a non-objectattributes/relationships:400 Bad Request. - A
typethat does not match the resource onPOST:409 Conflict.
Additional Context
Checked on api-platform/core v4.4.4, Symfony 7.4, PHP 8.5, in an empty Symfony app. The related code in src/JsonApi/Serializer is the same on main, except for the error status cast (#8366).
The app has only FrameworkBundle, TwigBundle and ApiPlatformBundle, with this config:
$c->extension('api_platform', [
'mapping' => ['paths' => ['%kernel.project_dir%/src/ApiResource']],
'formats' => ['jsonapi' => ['application/vnd.api+json']],
'error_formats' => ['jsonapi' => ['application/vnd.api+json'], 'jsonproblem' => ['application/problem+json']],
'doctrine' => ['enabled' => false],
]);
All requests send Accept: application/vnd.api+json and, when they have a body, Content-Type: application/vnd.api+json. The responses are from the prod environment.
- Lenguaje dominante
- PHP
- Estrellas
- 2.6k
- Forks
- 989
- Merge medio
- 1 d 23 h
- PR fusionados (30 d)
- 102
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de api-platform/core
-
JSON:API: resource schemas (`*.jsonapi`) have `properties` but no `type: object`Posiblemente ocupada @ousamabenyounes la tomó hace 1 día. Abierto
Dificultad 2/5 Menos de una hora Aptitud para principiantes 80/100
api-platform/core#8701 ·
Los mantenedores suelen responder en 1 día
-
JSON:API: `JsonApiCollectionBaseSchemaNoPagination` declares `data` as `type: array` without `items`Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
api-platform/core#8699 ·
Los mantenedores suelen responder en 1 día
-
api:openapi:export --spec-version=3.0.0 outputs `webhooks`, which is invalid in OpenAPI 3.0Posiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
api-platform/core#8690 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
api-platform/core#8680 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
api-platform/core#8725 ·
Los mantenedores suelen responder en 1 día
Todos los issues de api-platform/core
Issues similares
-
InvoiceSettled is answered 200 when the invoice cannot be re-fetched, so BTCPay never redelivers itAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
btcpayserver/woocommerce-greenfield-plugin#93 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
opnsense/core#11052 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
needs triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
grokability/snipe-it#19857 ·
Los mantenedores suelen responder en 1 día