Skip to content

Commit

Permalink
Fix a rare issue with same-host restriction causing updates to fail.
Browse files Browse the repository at this point in the history
WordPress has a security feature where the HTTP API will reject all requests that are sent to another site hosted on the same server as the current site (IP match) or a local host/IP, unless the host exactly matches the current site. This feature is opt-in, but apparently some people (or security plugins?) enable it.

This can be a problem when the update metadata is on the same server as your site, but not on the exact same hostname. The aforementioned security restriction will cause updates to fail for no apparent reason.

The patch fixes the issue by using the "http_request_host_is_external" filter to explicitly allow the host that the metadata URL points to.
  • Loading branch information
YahnisElsts committed Jan 9, 2016
1 parent c6f4e48 commit 7a29fda
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions plugin-update-checker.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class PluginUpdateChecker_2_3 {

private $upgradedPluginFile = null; //The plugin that is currently being upgraded by WordPress.

private $metadataHost = ''; //The host component of $metadataUrl.

/**
* Class constructor.
*
Expand Down Expand Up @@ -157,6 +159,10 @@ protected function installHooks(){
add_filter('upgrader_package_options', array($this, 'setUpgradedPluginFromOptions'), 10, 1);
add_filter('upgrader_post_install', array($this, 'clearUpgradedPlugin'), 10, 1);
add_action('upgrader_process_complete', array($this, 'clearUpgradedPlugin'), 10, 1);

//Allow HTTP requests to the metadata URL even if it's on a local host.
$this->metadataHost = @parse_url($this->metadataUrl, PHP_URL_HOST);
add_filter('http_request_host_is_external', array($this, 'allowMetadataHost'), 10, 2);
}

/**
Expand Down Expand Up @@ -194,6 +200,31 @@ public function getCronHookName() {
return $this->cronHook;
}

/**
* Explicitly allow HTTP requests to the metadata URL.
*
* WordPress has a security feature where the HTTP API will reject all requests that are sent to
* another site hosted on the same server as the current site (IP match), a local host, or a local
* IP, unless the host exactly matches the current site.
*
* This feature is opt-in (at least in WP 4.4). Apparently some people enable it.
*
* That can be a problem when you're developing your plugin and you decide to host the update information
* on the same server as your test site. Update requests will mysteriously fail.
*
* We fix that by adding an exception for the metadata host.
*
* @param bool $allow
* @param string $host
* @return bool
*/
public function allowMetadataHost($allow, $host) {
if ( strtolower($host) === strtolower($this->metadataHost) ) {
return true;
}
return $allow;
}

/**
* Retrieve plugin info from the configured API endpoint.
*
Expand Down

0 comments on commit 7a29fda

Please sign in to comment.