Make WordPress Core

Opened 11 hours ago

Last modified 11 hours ago

#65230 new defect (bug)

`redirect_canonical()` fails to redirect slug-based attachment URLs when `wp_attachment_pages_enabled` is disabled

Reported by: dd32's profile dd32 Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.4
Component: Media Keywords: has-patch has-unit-tests
Focuses: Cc:

Description

When attachment pages are disabled (wp_attachment_pages_enabled = 0) and pretty permalinks are in use, visiting an attachment via its slug URL (e.g. /my-image-jpg/) returns a 200 with the attachment page rendered, instead of redirecting to the file. The query-string form (?attachment_id=123) for the same attachment correctly redirects.

This is a follow-up to #59866, which addressed the logged-in/anonymous discrepancy but did not cover the slug-URL code path.

Steps to reproduce

  1. Enable pretty permalinks (e.g. /%postname%/).
  2. Set wp_attachment_pages_enabled to 0.
  3. Upload any media file.
  4. Visit the attachment's pretty permalink, e.g. /my-image-jpg/.

Expected: 301 redirect to the file URL (e.g. /wp-content/uploads/2026/05/my-image.jpg).
Actual: 200 response with an attachment page rendered.

Cause

In src/wp-includes/canonical.php (~line 553), inside the is_attachment() && ! get_option( 'wp_attachment_pages_enabled' ) block:

$attachment_id   = get_query_var( 'attachment_id' );
$attachment_post = get_post( $attachment_id );

get_query_var( 'attachment_id' ) is only populated for ?attachment_id=ID URLs. For slug-based URLs the query var is empty, so get_post( '' ) returns null, $attachment_url is falsy, and the redirect branch silently falls through.

Prior tickets

  • #59866 — Attachment pages are only disabled for users that are logged in (fixed in 6.4.3; this ticket covers the slug-URL gap missed there)
  • #57913 — Attachment pages need to have an "on" toggle (introduced the option)

Note: AI was used in the preparation of this ticket.

Change History (2)

#1 @dd32
11 hours ago

  • Version set to 6.4

This ticket was mentioned in PR #11816 on WordPress/wordpress-develop by @dd32.


11 hours ago
#2

  • Keywords has-patch has-unit-tests added

When wp_attachment_pages_enabled is 0 and pretty permalinks are active, accessing an attachment via its slug URL (e.g. /my-image-jpg/) currently returns a 200 with an attachment page rendered, instead of redirecting to the underlying file. The query-string variant (?attachment_id=123) for the same attachment correctly redirects.

The cause is in redirect_canonical() (src/wp-includes/canonical.php around line 553): the code retrieves the attachment ID via get_query_var( attachment_id ), which is only populated for ?attachment_id=N URLs. For slug-based attachment URLs the query var is empty, so get_post() receives an empty value, returns null, and the redirect is silently skipped.

This change falls back to get_queried_object_id() when the attachment_id query var is empty, so the attachment ID resolves correctly for both URL forms. Tests are added in tests/phpunit/tests/canonical/attachmentRedirect.php covering the slug and query-var URL forms, attachments on private/draft parents (the privacy guard at canonical.php ~line 800), and the no-redirect case when attachment pages remain enabled.

Note: See TracTickets for help on using tickets.