[wp-trac] [WordPress Trac] #65411: Don’t let ?s= override singular URLs

WordPress Trac noreply at wordpress.org
Thu Jun 4 14:03:01 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. 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.

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:3>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list