[wp-trac] [WordPress Trac] #65411: Don’t let ?s= override singular URLs
WordPress Trac
noreply at wordpress.org
Thu Jun 4 14:02:30 UTC 2026
#65411: Don’t let ?s= override singular URLs
----------------------------+------------------------------
Reporter: jonoaldersonwp | Owner: (none)
Type: defect (bug) | Status: new
Priority: low | Milestone: Awaiting Review
Component: Rewrite Rules | Version:
Severity: normal | Resolution:
Keywords: | Focuses: ui, performance
----------------------------+------------------------------
Description changed by jonoaldersonwp:
Old description:
> When a post URL is shared from Twitter/X, the app may append a source-
> tracking parameter such as `?s=20`.
>
> For example, a valid post URL like https://www.example.com/some-article/
> can become https://www.example.com/some-article/?s=20 (where `20` varies
> by device/location/context) when shared.
>
> A visitor clicking that link expects to see the article. Instead,
> WordPress may treat `s=20` as an internal search query. Depending on the
> site, theme, plugins, and rewrite state, this can load search results for
> `20`, change the template context, or produce a 404 error.
>
> That is a bad outcome for users, and often an expensive one for sites.
> Singular content is commonly cached. Search results and 404s often are
> not.
>
> == Broader issue ==
>
> The `s` query var is a long-standing part of WordPress search behaviour,
> and URLs like https://www.example.com/?s=example and
> https://www.example.com/some-taxonomy/?s=filter (which filters the
> existing request) continue to work.
>
> But `s` is also a very short, generic parameter. WordPress cannot assume
> that every external use of `?s=` is intended to trigger site search.
>
> Twitter/X is the clearest current example, but the same failure mode can
> occur whenever another platform, app, email client, CMS, analytics
> system, or sharing tool appends `s` to an otherwise valid WordPress URL.
>
> A third-party tracking parameter should not be able to override a request
> that already resolves to a post, page, attachment, or other singular
> object.
>
> == Proposed change ==
>
> Could WordPress prefer the resolved singular object when a request
> contains both /some-existing-post/ and `?s=<value>`?
>
> In practice: https://www.example.com/some-article/?s=20 should load the
> post at /some-article/, not a search results page for `20`.
>
> This should not remove or deprecate normal search URLs. These should
> continue to behave as searches:
>
> https://www.example.com/?s=example
> https://www.example.com/search/example/
>
> The change should apply only where the path portion of the request
> already resolves to a singular object.
>
> == Possible implementation direction ==
>
> This may be best handled during request parsing or main query resolution.
>
> At a high level:
>
> - If the request path resolves to a singular object, do not let s turn
> the main query into a search.
> - Preserve the raw `s` value in `$_GET` for plugins and custom code that
> need to inspect it.
> - Ensure template selection, conditional tags, and canonical behaviour
> match the resolved singular object.
> - Consider a filter for sites that intentionally use `?s=` on singular
> URLs.
>
> == Compatibility considerations ==
>
> Some sites may intentionally use `?s=` on singular URLs for custom
> behaviour, for example:
>
> https://www.example.com/product/example-product/?s=blue
>
> For that reason, the safest approach may be to change only the main query
> interpretation, while preserving the raw request parameter.
>
> It is also worth discussing whether this should apply to all `s` values,
> or only to values that look like third-party source identifiers, such as
> numeric values. Applying it consistently to all `s` values may be simpler
> and less surprising: if the path resolves to a singular object, the
> singular object wins.
>
> == Questions for discussion ==
> - At what level should this be addressed (given that we can't rely on
> `is_search()` etc)?
> - Should the rule apply to all `s` values, or only source-like values
> such as numbers?
> - Is a compatibility filter needed?
>
> == Why this belongs in Core ==
>
> This is a Core routing and query interpretation issue, not a theme-
> specific or plugin-specific problem.
>
> A valid shared URL to a singular object should not become a search or 404
> because a third-party platform appended a generic `s` parameter.
> WordPress can make this more resilient by allowing the resolved singular
> path to take precedence over accidental search parameters.
New description:
When a post URL is shared from Twitter/X, the app may append a source-
tracking parameter such as `?s=20`.
For example, a valid post URL like https://www.example.com/some-article/
can become https://www.example.com/some-article/?s=20 (where `20` varies
by device/location/context) when shared.
A visitor clicking that link expects to see the article. Instead,
WordPress may treat `s=20` as an internal search query. Depending on the
site, theme, plugins, and rewrite state, this can load search results for
`20`, change the template context, or produce a 404 error.
That is a bad outcome for users, and often an expensive one for sites.
Singular content is commonly cached. Search results and 404s often are
not.
== Broader issue ==
The `s` query var is a long-standing part of WordPress search behaviour,
and URLs like https://www.example.com/?s=example and
https://www.example.com/some-taxonomy/?s=filter (which filters the
existing request) continue to work.
But `s` is also a very short, generic parameter. WordPress cannot assume
that every external use of `?s=` is intended to trigger site search.
Twitter/X is the clearest current example, but the same failure mode can
occur whenever another platform, app, email client, CMS, analytics system,
or sharing tool appends `s` to an otherwise valid WordPress URL.
A third-party tracking parameter should not be able to override a request
that already resolves to a post, page, attachment, or other singular
object.
== Proposed change ==
Could WordPress prefer the resolved singular object when a request
contains both `/some-existing-post/` and `?s=<value>`?
In practice: https://www.example.com/some-article/?s=20 should load the
post at `/some-article/`, not a search results page for `20`.
This should not remove or deprecate normal search URLs. URLs like
https://www.example.com/?s=example and
https://www.example.com/search/example/ should continue to behave as
search results.
The change should apply only where the path portion of the request already
resolves to a singular object.
== Possible implementation direction ==
This may be best handled during request parsing or main query resolution.
At a high level:
- If the request path resolves to a singular object, do not let s turn the
main query into a search.
- Preserve the raw `s` value in `$_GET` for plugins and custom code that
need to inspect it.
- Ensure template selection, conditional tags, and canonical behaviour
match the resolved singular object.
- Consider a filter for sites that intentionally use `?s=` on singular
URLs.
== Compatibility considerations ==
Some sites may intentionally use `?s=` on singular URLs for custom
behaviour, for example:
https://www.example.com/product/example-product/?s=blue
For that reason, the safest approach may be to change only the main query
interpretation, while preserving the raw request parameter.
It is also worth discussing whether this should apply to all `s` values,
or only to values that look like third-party source identifiers, such as
numeric values. Applying it consistently to all `s` values may be simpler
and less surprising: if the path resolves to a singular object, the
singular object wins.
== Questions for discussion ==
- At what level should this be addressed (given that we can't rely on
`is_search()` etc)?
- Should the rule apply to all `s` values, or only source-like values such
as numbers?
- Is a compatibility filter needed?
== Why this belongs in Core ==
This is a Core routing and query interpretation issue, not a theme-
specific or plugin-specific problem.
A valid shared URL to a singular object should not become a search or 404
because a third-party platform appended a generic `s` parameter. WordPress
can make this more resilient by allowing the resolved singular path to
take precedence over accidental search parameters.
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/65411#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list