Make WordPress Core

Changeset 59724


Ignore:
Timestamp:
01/28/2025 11:20:48 PM (20 months ago)
Author:
johnbillion
Message:

Security: Always include the no-store and private directives in the Cache-Control header when setting headers that prevent caching.

The intention of these headers is to prevent any form of caching, whether that's in the browser or in an intermediate cache such as a proxy server. These directives instruct an intermediate cache to not store the response in their cache for any user – not just for logged-in users.

This does not affect the caching behaviour of assets within a page such as images, CSS, and JavaScript files.

Props kkmuffme, devansh2002, johnbillion.

Fixes #61942

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/functions.php

    r59712 r59724  
    14901490 *
    14911491 * The several different headers cover the different ways cache prevention
    1492  * is handled by different browsers.
     1492 * is handled by different browsers or intermediate caches such as proxy servers.
    14931493 *
    14941494 * @since 2.8.0
    14951495 * @since 6.3.0 The `Cache-Control` header for logged in users now includes the
    14961496 *              `no-store` and `private` directives.
     1497 * @since 6.8.0 The `Cache-Control` header now includes the `no-store` and `private`
     1498 *              directives regardless of whether a user is logged in.
    14971499 *
    14981500 * @return array The associative array of header names and field values.
    14991501 */
    15001502function wp_get_nocache_headers() {
    1501         $cache_control = ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() )
    1502                 ? 'no-cache, must-revalidate, max-age=0, no-store, private'
    1503                 : 'no-cache, must-revalidate, max-age=0';
     1503        $cache_control = 'no-cache, must-revalidate, max-age=0, no-store, private';
    15041504
    15051505        $headers = array(
  • trunk/tests/e2e/specs/cache-control-headers-directives.test.js

    r56926 r59724  
    2828                await context.close();
    2929
     30                expect( responseHeaders ).toEqual( expect.not.objectContaining( { "cache-control": "no-cache" } ) );
    3031                expect( responseHeaders ).toEqual( expect.not.objectContaining( { "cache-control": "no-store" } ) );
    3132                expect( responseHeaders ).toEqual( expect.not.objectContaining( { "cache-control": "private" } ) );
     
    4142                const responseHeaders = response.headers();
    4243
     44                expect( responseHeaders[ 'cache-control' ] ).toContain( 'no-cache' );
     45                expect( responseHeaders[ 'cache-control' ] ).toContain( 'no-store' );
     46                expect( responseHeaders[ 'cache-control' ] ).toContain( 'private' );
     47        } );
     48
     49        test(
     50                'Correct directives present in cache control header when not logged in on 404 page.',
     51                async ( { browser }
     52                ) => {
     53                const context = await browser.newContext();
     54                const loggedOutPage = await context.newPage();
     55
     56                const response = await loggedOutPage.goto( '/this-does-not-exist/' );
     57                const responseHeaders = response.headers();
     58                const responseStatus = response.status();
     59
     60                // Dispose context once it's no longer needed.
     61                await context.close();
     62
     63                expect( responseStatus ).toBe( 404 );
     64                expect( responseHeaders[ 'cache-control' ] ).toContain( 'no-cache' );
    4365                expect( responseHeaders[ 'cache-control' ] ).toContain( 'no-store' );
    4466                expect( responseHeaders[ 'cache-control' ] ).toContain( 'private' );
Note: See TracChangeset for help on using the changeset viewer.