Opened 4 months ago
Last modified 5 days ago
#65050 reviewing defect (bug)
REST API: Comments controller returns 403 instead of 404 for invalid post ID in update_item()
| Reported by: | saratheonline | Owned by: | westonruter |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | REST API | Version: | 7.0 |
| Severity: | normal | Keywords: | has-patch changes-requested has-unit-tests |
| Cc: | Focuses: | coding-standards |
Description
In WP_REST_Comments_Controller, the update_item() method returns HTTP
403 (Forbidden) when an invalid post ID is provided, but the correct status
code is 404 (Not Found).
The same file returns 404 for the identical scenario in
get_item()
(line 418), making this inconsistent within the same controller.
403 implies the client lacks permission. 404 is correct here because
the post does not exist — it is a missing resource, not an authorization
failure.
Affected code (class-wp-rest-comments-controller.php)
if ( empty( $post ) ) {
return new WP_Error(
'rest_comment_invalid_post_id',
__( 'Invalid post ID.' ),
array( 'status' => 403 ) // incorrect
);
}
Proposed Fix
array( 'status' => 404 )
Change History (13)
This ticket was mentioned in PR #11529 on WordPress/wordpress-develop by @saratheonline.
4 months ago
#1
#2
@
4 months ago
- Focuses coding-standards added
Tested patch: https://github.com/WordPress/wordpress-develop/pull/11529
Environment:
- WordPress: 7.1-alpha-62161-src
- PHP: 8.3.30
- Browser: Chrome
- Database: MySQL 8.4.8
- OS: Ubuntu
Steps I followed:
- Confirmed that 'update_item()' in 'WP_REST_Comments_Controller' returns a 403 status when an invalid post ID is provided.
- Verified that the same scenario in
get_item()correctly returns a 404 status. - This creates inconsistency within the same controller.
Agree that 404 is the correct response here, as the post does not exist and this is not a permission issue.
Tested the proposed fix and it resolves the issue as expected without introducing any regressions.
#5
@
4 months ago
- Keywords needs-testing removed
Patch Testing Report
Patch Tested: https://github.com/WordPress/wordpress-develop/pull/11529
Environment
- WordPress: 7.1-alpha-62161-src
- PHP: 8.3.30
- Server: nginx/1.29.5
- Database: mysqli (Server: 8.4.8 / Client: mysqlnd 8.3.30)
- Browser: Chrome 147.0.0.0
- OS: Windows 10/11
- Theme: Twenty Twenty-Five 1.4
- MU Plugins: None activated
- Plugins:
- Test Reports 1.2.1
Steps taken
- Ensure you have the Application password from "Users > Profile".
- In your terminal, run this command:
curl -X POST http://localhost:8889/wp-json/wp/v2/comments/1 \ -u "admin" \ -H "Content-Type: application/json" \ -d '{"post": 9999}' - You'll be prompted to enter a password. Enter the password you got from Application Password.
- Perform steps 2 - 3 before and after applying the patch.
- ✅ Patch is solving the problem.
Expected result
- A 404 status code response is returned when you try to update with a non-existent post ID.
Additional Notes
- Patch fixes the issue, updating keyword (removing "needs-testing"). Add it back if needed.
Screenshots/Screencast with results
- Before:
- After:
#6
@
3 months ago
Tested PR https://github.com/WordPress/wordpress-develop/pull/11529
I created a post and comment locally, then called WP_REST_Comments_Controller::update_item() with that comment ID and post => 999999.
Before the patch, the response was rest_comment_invalid_post_id with status 403.
After the patch, the same error code returns status 404.
This matches the behavior in get_item() and looks correct to me. Patch tests well.
#7
@
3 months ago
Removing trunk version as this is not going to be shipped with WP 7.0 but in the next releases.
This ticket was mentioned in PR #12545 on WordPress/wordpress-develop by @dhrupo.
4 weeks ago
#8
- Keywords has-unit-tests added
## Summary
WP_REST_Comments_Controller::update_item() returned HTTP 403 (Forbidden) when the request targeted a non-existent post ID (e.g. PUT /wp/v2/comments/<id> with post set to a missing post). The correct status is 404 (Not Found): the post is a missing resource, not an authorization failure.
This also makes update_item() consistent with get_item(), which already returns 404 for the same "post does not exist" scenario within the same controller.
## Changes
class-wp-rest-comments-controller.php: change therest_comment_invalid_post_iderror status from403to404inupdate_item().rest-comments-controller.php(tests): update thetest_update_comment_invalid_post_idassertion to expect404.
The error code (rest_comment_invalid_post_id) is intentionally unchanged to preserve backwards compatibility for clients matching on it. The create_item 403 responses ("Sorry, you are not allowed to create this comment without a post.") are genuine authorization checks and are left untouched.
## Relationship to #11529
This completes the work started in #11529 by @saratheonline, which made the code change but left the existing unit test asserting 403, causing CI to fail. @westonruter requested changes noting the test needed updating. This PR includes both the code fix and the corresponding test update so the suite passes.
## Testing
Reproduced red → green:
- With the unpatched code, updating
test_update_comment_invalid_post_idto expect404fails:Failed asserting that 403 is identical to 404. - After the one-line controller fix, the test passes.
Full controller suite green (verified in the local Docker environment):
WP_Test_REST_Comments_Controller: OK (142 tests, 675 assertions)
Manual reproduction:
curl -X POST http://localhost:8889/wp-json/wp/v2/comments/1 \
-u "admin:<app-password>" \
-H "Content-Type: application/json" \
-d '{"post": 9999}'
# Before: 403 Forbidden
# After: 404 Not Found
Props saratheonline.
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.8
Used for: Reproducing the failing test, applying the fix and the test update, and running the test suite. All changes were reviewed by me.
This ticket was mentioned in Slack in #core-test by noruzzaman. View the logs.
12 days ago
@mirmpro commented on PR #12545:
12 days ago
#10
Test Report
Patch tested: https://github.com/WordPress/wordpress-develop/pull/12545
Environment
- WordPress: 7.1-alpha
- Subdirectory: No
- PHP: 7.4.33
- Server: PHP.wasm
- Database: WP_SQLite_Driver
- Browser: Chrome 150.0.0.0
- OS: macOS
- Theme: Twenty Twenty-Five
- MU Plugins: None activated
- Plugins: None
Steps taken
- Launched the WordPress testing environment via the Playground PR preview URL for PR #12545.
- Opened the browser developer console while logged in as Administrator.
- Executed a REST API request targeting an existing comment (
/wp/v2/comments/1) and attempted to update its associatedpostto a non-existent post ID (99999):`javascript wp.apiFetch({
path: '/wp/v2/comments/1',
method: 'POST',
data: { post: 99999 }
}).catch( error => console.log('Response Status:', error.data.status, error) );
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)


update_item()was returning HTTP 403 (Forbidden) when a non-existentTrac ticket: https://core.trac.wordpress.org/ticket/65050
Fixes: #65050
## Use of AI Tools