Opened 5 weeks ago
Last modified 5 weeks ago
#65072 assigned defect (bug)
Registering a query_var called 'preview_nonce' stops previews from working.
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Query | Keywords: | has-patch has-unit-tests |
| Focuses: | Cc: |
Description
Summary
The static front page fallback in WP_Query::get_posts() line ~2042 sets is_page = true and is_home = false, but does not update is_singular. This causes the query to generate incorrect SQL — using post_type = 'post' instead of post_type = 'page' — and return zero results.
The equivalent check in parse_query() (line ~1057) correctly maintains the invariant by recalculating is_singular at line 1135. The get_posts() backstop does not.
How to trigger
The backstop fires when parse_query() fails to detect the static front page because $this->query contains unexpected public query vars (anything not in the allowlist of preview, page, paged, cpage). This can happen when a plugin registers a query var that collides with a parameter WordPress core uses in preview URLs — for example, registering preview_nonce as a public query var.
Steps to reproduce
- Register preview_nonce as a public query var:
add_filter( 'query_vars', function ( $vars ) { $vars[] = 'preview_nonce'; return $vars; } ); - Set a static front page in Settings → Reading
- Visit /?preview_id=<page_id>&preview_nonce=<valid_nonce>&preview=true
Expected: The static front page content is displayed.
Actual: The blog post index is displayed. The preview URL is redirected with preview=true stripped.
What happens internally
parse_query()line ~1057: Thearray_diffcheck fails becausepreview_nonceis not in the allowlist.is_homestaystrue,is_pagestaysfalse,is_singularstaysfalse.
get_posts()line ~2046: The backstop fires becauseis_homeistrueand$query_vars['preview']is'true'. It setsis_page = true,is_home = false, andpage_idto the front page ID. But it does not setis_singular = true.
get_posts()line ~2618:$post_type_whereis correctly set topost_type = 'page'based onis_page = true.
get_posts()line ~2705: The! $this->is_singularbranch is entered. This branch builds its own combined post_type + post_status clause. Since$post_typeis empty (line ~2003), line ~2713 defaults toarray('post'), overriding the correctpost_type_wherefrom step 3.
- The resulting SQL is
WHERE ID = <page_id> AND post_type = 'post', which returns zero rows because the front page is apage.
- With zero results,
redirect_canonicalstripspreview=truefrom the URL and redirects. On the second request, neitherparse_query()nor the backstop can identify the request as the static front page.
Note
I've fixed the plugin which exposed this issue, but the is_singular invariant violation in the backstop is a core issue.
Change History (1)
This ticket was mentioned in PR #11571 on WordPress/wordpress-develop by @dsas.
5 weeks ago
#1
- Keywords has-patch has-unit-tests added
The static front page backstop in
WP_Query::get_posts()setsis_page = trueandis_home = false, but did not updateis_singular. This caused the query to generate incorrect SQL — usingpost_type = 'post'instead ofpost_type = 'page'— and return zero results.The equivalent check in
parse_query()correctly maintains the invariant by recalculatingis_singularat line 1135. Theget_posts()backstop now does the same.The backstop fires when
parse_query()fails to detect the static front page because$this->querycontains unexpected public query vars (anything not in the allowlist ofpreview,page,paged,cpage). This can happen when a plugin registers a query var that collides with a parameter WordPress core uses in preview URLs.Trac ticket: https://core.trac.wordpress.org/ticket/65072
## Use of AI Tools