Make WordPress Core

Opened 5 weeks ago

Last modified 26 hours ago

#64837 reopened enhancement

Disable pings/trackbacks for local, development, and staging environments

Reported by: cagrimmett's profile cagrimmett Owned by: ramonopoly's profile ramonopoly
Milestone: 7.1 Priority: normal
Severity: normal Version:
Component: Pings/Trackbacks Keywords: has-patch has-unit-tests
Focuses: Cc:

Description

When WP_ENVIRONMENT_TYPE is local, development, or staging, pingbacks and trackbacks should be disabled.

Unless one remembers to go in and disable pingbacks/trackbacks on a non-production environment, pings will be sent out when posts are added or updated, which is a common workflow when testing. This is not ideal and creates confusion on the receiving end. Disabling them on non-production environments default would be a better experience.

  • Both outgoing and incoming should be disabled.
  • If the environment type is not set, or is set to production, pings and trackbacks should be left as default (open/enabled).
  • A filter should be added so developers can override this change if pingbacks or trackbacks are needed in a non-production environment.

Change History (20)

#1 @khushipatel15
5 weeks ago

Inlcude this code snippet in wp-includes/default-filters.php folder and perform unit test.

<?php
/**
 * Core environment-specific filters for pingbacks and trackbacks.
 *
 * @package WordPress
 * @subpackage Core
 * @since 6.6.0
 */

/**
 * Conditionally disables outgoing pingbacks/trackbacks in non-production environments.
 *
 * Prevents the dispatch of pingbacks/trackbacks when the environment type is 'local',
 * 'development', or 'staging', unless overridden by a filter.
 *
 * @since 6.6.0
 *
 * @param bool $send Whether to send the pingback. Default true.
 * @return bool True to send, false to prevent sending.
 */
function wp_disable_outgoing_pings_trackbacks_in_dev_envs( $send ) {
	$env_type = wp_get_environment_type();

	/**
	 * Filters whether to prevent WordPress from disabling pings/trackbacks
	 * in non-production environments.
	 *
	 * Returning `true` will allow pings and trackbacks to function normally
	 * even when the environment type is 'local', 'development', or 'staging'.
	 * This filter can be used to re-enable pings/trackbacks if they are
	 * intentionally needed in a development environment.
	 *
	 * @since 6.6.0
	 *
	 * @param bool   $override If `true`, the disablement logic is skipped. Default `false`.
	 * @param string $env_type The current environment type (e.g., 'local', 'development', 'staging', 'production').
	 */
	if ( apply_filters( 'wp_override_disable_pings_trackbacks_in_dev_envs', false, $env_type ) ) {
		return $send;
	}

	if ( in_array( $env_type, array( 'local', 'development', 'staging' ), true ) ) {
		return false; // Prevent outgoing pingbacks.
	}

	return $send;
}
add_filter( 'pre_pingback_send', 'wp_disable_outgoing_pings_trackbacks_in_dev_envs' );


/**
 * Conditionally disables incoming pingbacks/trackbacks in non-production environments
 * by removing the 'pingback.ping' XML-RPC method.
 *
 * Prevents WordPress from processing incoming pingbacks/trackbacks when the
 * environment type is 'local', 'development', or 'staging', unless overridden by a filter.
 *
 * @since 6.6.0
 *
 * @param array<string, callable> $methods Associative array of XML-RPC methods.
 * @return array<string, callable> Modified associative array of XML-RPC methods.
 */
function wp_disable_incoming_pings_trackbacks_in_dev_envs( $methods ) {
	$env_type = wp_get_environment_type();

	/** This filter is documented in wp_disable_outgoing_pings_trackbacks_in_dev_envs() */
	if ( apply_filters( 'wp_override_disable_pings_trackbacks_in_dev_envs', false, $env_type ) ) {
		return $methods;
	}

	if ( in_array( $env_type, array( 'local', 'development', 'staging' ), true ) ) {
		// Remove the 'pingback.ping' method to disable incoming pingbacks.
		if ( isset( $methods['pingback.ping'] ) ) {
			unset( $methods['pingback.ping'] );
		}
	}

	return $methods;
}
add_filter( 'xmlrpc_methods', 'wp_disable_incoming_pings_trackbacks_in_dev_envs' );
Last edited 8 days ago by dd32 (previous) (diff)

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


8 days ago
#2

  • Keywords has-patch has-unit-tests added

## Trac Ticket

https://core.trac.wordpress.org/ticket/64837

## Summary

When WP_ENVIRONMENT_TYPE is local, development, or staging, pingbacks and trackbacks are sent when posts are published. This creates confusion on the receiving end and is unnecessary for testing workflows.

This PR disables all outgoing and incoming pings in non-production environments by default:

  • Outgoing: Removes do_all_pingbacks, do_all_trackbacks, and generic_ping callbacks from the do_all_pings action (at priority 1, before they fire at priority 10). Enclosures (do_all_enclosures) are intentionally left untouched.
  • Incoming pingbacks: Filters xmlrpc_methods to remove pingback.ping.
  • Incoming trackbacks: Hooks pre_trackback_post to reject trackbacks before they are processed.

Note: pings_open() is intentionally not filtered, because it would suppress the X-Pingback header that wp_install_maybe_enable_pretty_permalinks() relies on to verify rewrite rules during fresh installs.

### Override filter

Developers can re-enable pings in non-production environments:

add_filter( 'wp_should_disable_pings_for_environment', '__return_false' );

Or disable pings even in production:

add_filter( 'wp_should_disable_pings_for_environment', '__return_true' );

## Test instructions

  1. Set WP_ENVIRONMENT_TYPE to local, development, or staging
  2. Publish a post with links to external sites
  3. Verify no outgoing pingbacks or trackbacks are sent
  4. Verify incoming pingback XML-RPC calls are rejected
  5. Verify incoming trackbacks are rejected
  6. Change WP_ENVIRONMENT_TYPE to production and verify pings work normally
  7. Run npm run test:php -- --filter Tests_Comment_DisablePingsForEnvironment

## Files changed

  • src/wp-includes/comment.php — Four new functions: wp_should_disable_pings_for_environment() (public API with filter), wp_disable_outgoing_pings_for_environment(), wp_disable_trackback_for_environment(), wp_disable_xmlrpc_pingback_for_environment()
  • src/wp-includes/default-filters.php — Register the three hook callbacks
  • tests/phpunit/tests/comment/disablePingsForEnvironment.php — 17 new tests covering all environment types, filter overrides, and edge cases

#3 follow-up: @ramonopoly
2 days ago

  • Owner set to ramonopoly
  • Resolution set to fixed
  • Status changed from new to closed

In 62231:

Disable pings/trackbacks for local, development, and staging environments

When WP_ENVIRONMENT_TYPE is not production, disable pingbacks and trackbacks.

Otherwise, when WP_ENVIRONMENT_TYPE is localdevelopment, or staging, pingbacks and trackbacks are sent when posts are published. This creates confusion on the receiving end and is unnecessary for testing workflows.

Props arcangelini, cagrimmett, ramonopoly, tyxla.

Fixes #64837.

@ramonopoly commented on PR #11476:


2 days ago
#4

Committed in r62231 and 5accf7de0ce5078b47e5941aa32b2e560eae80af

#5 @swissspidy
2 days ago

  • Milestone changed from Awaiting Review to 7.0

#6 @swissspidy
2 days ago

  • Milestone changed from 7.0 to 7.1

#7 @khushipatel15
2 days ago

@ramonopoly kindly please assist me with the issue of why am i not given props.

#8 @swissspidy
2 days ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Can we find a more elegant way to address this that doesn't require adding 4 (!) new functions?

#9 @khushipatel15
2 days ago

@swissspidy , we can use this function instead ?

function mytheme_disable_pings_in_dev() {
    $env_type = wp_get_environment_type();

    if (apply_filters('wp_override_disable_pings_trackbacks_in_dev_envs', false, $env_type)) {
        return false;
    }

    return in_array($env_type, ['local', 'development', 'staging'], true);
}

add_filter('pre_pingback_send', function ($send) {
    return mytheme_disable_pings_in_dev() ? false : $send;
});

add_filter('xmlrpc_methods', function ($methods) {
    if (mytheme_disable_pings_in_dev() && isset($methods['pingback.ping'])) {
        unset($methods['pingback.ping']);
    }
    return $methods;
});

#10 @ramonopoly
2 days ago

kindly please assist me with the issue of why am i not given props.

It was an oversight, apologies. I'll make sure the follow up is correct - looks like there's going to be one.

Can we find a more elegant way to address this that doesn't require adding 4 (!) new functions?

Any suggestions to help move your request along?

cc @arcangelini

#11 in reply to: ↑ 3 @ocean90
2 days ago

@ramonopoly According to The Path Forward for WordPress 7.0 "trunk is closed to commits for the 7.1 release until further notice". Please revert the commit from trunk. Thank you!

#12 @ramonopoly
2 days ago

In 62233:

REVERT r62231: Disable pings/trackbacks for local, development, and staging environments

Commits to trunk have been paused for 7.0.

See: https://make.wordpress.org/core/2026/04/02/the-path-forward-for-wordpress-7-0/

Props arcangelini, cagrimmett, ramonopoly, tyxla, ocean90, khushipatel15.

Follow-up to [64837].

See #64837.

#13 @ramonopoly
2 days ago

Please revert the commit from trunk. Thank you!

Thanks for the prompt heads up, @ocean90. Done.

#15 @arcangelini
39 hours ago

@swissspidy @ramonopoly

Each function serves a distinct hook with a distinct signature. I explored collapsing them, but the options were either inline closures in default-filters.php (breaks that file's named-callback convention) or a single dispatcher using current_filter() (uglier than the four small functions).

Happy to revisit if you feel strongly, but I'd prefer to leave it as-is.

#16 follow-up: @ramonopoly
36 hours ago

Happy to revisit if you feel strongly, but I'd prefer to leave it as-is.

In my mind I think it's fine to leave the PR as is until we can commit it (again). There are different actions and therefore different signatures. As far as I can tell, each function has a single responsibility.

There's still time until the commit pause is over to wait for actionable feedback or an alternative proposal.

add_filter('pre_pingback_send'

Is there any documentation for this filter? I can't find any evidence for its existence. Maybe pre_ping was meant. Apologies in advance if it's documented somewhere and I've just missed it.

Thanks, all!

#17 in reply to: ↑ 16 @arcangelini
28 hours ago

Replying to ramonopoly:

add_filter('pre_pingback_send'

Is there any documentation for this filter? I can't find any evidence for its existence. Maybe pre_ping was meant. Apologies in advance if it's documented somewhere and I've just missed it.

I am not seeing it anywhere either. Happy to add it though if its something that should be here.

#18 @ramonopoly
27 hours ago

@arcangelini Thanks for the reply.

Sorry, I wasn't clear. 😅 No action required, and nothing to do with https://github.com/WordPress/wordpress-develop/pull/11476

I was looking at @khushipatel15's code suggestions above in this trac ticket and wondering where add_filter('pre_pingback_send' came from.

Cheers!

#19 @khushipatel15
27 hours ago

Hello @ramonopoly , just for your information.

pre_pingback_send is a filter hook in WordPress that runs immediately before a pingback request is sent to a remote site.

Cheers! Have a good day!

#20 @ramonopoly
26 hours ago

pre_pingback_send is a filter hook in WordPress that runs immediately before a pingback request is sent to a remote site.

Thank you for the quick reply! I couldn't find it in use in the code or across any plugins.

Note: See TracTickets for help on using tickets.