Problem/Motivation
The JSON:API spec states:
A server MUST return 409 Conflict when processing a POST request in which the resource object’s type is not among the type(s) that constitute the collection represented by the endpoint. Source
And:
A server MUST return 409 Conflict when processing a PATCH request in which the resource object’s type or id do not match the server’s endpoint. Source
However, JsonApiDocumentTopLevelNormalizer::validateRequestBody() checks that a request body includes a "type" member but does not check that the value matches the resource type of the requested endpoint. The type can be an arbitrary string. This is a spec violation.
Types are already checked for relationships.
Steps to reproduce
1. Enable JSON:API on a standard content entity, e.g. node.
2. POST to /jsonapi/node/article with a valid attributes payload but set data.type to an unrelated/invalid string, e.g. "type": "not-a-real-resource-type".
3. The request succeeds and the node is created, but it should fail because the type does not match.
Proposed resolution
validateRequestBody() now compares data.type to the resource type of the endpoint. A mismatch triggers a 409 Conflict response, per the JSON:API spec. The check runs for both POST and PATCH, since both operations call the same denormalize() method.
Test coverage
A kernel test exercises the denormalizer directly with a mismatched type. Functional tests send a mismatched type on POST and on PATCH and assert a 409 response with the expected error message.
Issue fork drupal-3612597
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
benstallings commentedComment #4
ptmkenny commentedTests don't pass.
Comment #5
benstallings commentedComment #6
ptmkenny commentedThe IS still has "Remaining tasks" that need to be resolved before commit.
It looks like the current issue summary is AI-generated and not updated for the MR; for example, one task is "Determine whether this should also apply to PATCH requests," but the current MR already applies to PATCH requests. Also the summary begins with "When creating or updating a resource via JSON:API (POST/PATCH), JsonApiDocumentTopLevelNormalizer::validateRequestBody() only checks that data.type is present in the request body" so it's not clear why determining whether to apply it to PATCH would be a "Remaining task."
Another item is "Add test coverage" but the MR already adds test coverage. So is there more test coverage to be added, or is the current test coverage sufficient?
If this change needs a change record, the change record needs to be included so that it can be evaluated along with the code.
The IS needs to be rewritten and verified by a human to accurately summarize the issue.
Comment #7
benstallings commentedComment #8
benstallings commentedThanks for the feedback @ptmkenny. I've updated the summary to reflect the current state. I haven't contributed a change record before, but I'll see what I can do!
Comment #9
benstallings commentedchange record added.
Comment #10
ptmkenny commentedI rewrote the IS and change record. The real issue here is spec non-compliance.