Skip to content

Commit

Permalink
Validate api.yourls.org result when checking for new version (YOURLS#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ozh authored Apr 21, 2020
1 parent c2c2826 commit 2bc2bb1
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
5 changes: 3 additions & 2 deletions includes/functions-html.php
Original file line number Diff line number Diff line change
Expand Up @@ -935,9 +935,10 @@ function yourls_l10n_calendar_strings() {
function yourls_new_core_version_notice() {

$checks = yourls_get_option( 'core_version_checks' );
$latest = isset($checks->last_result->latest) ? yourls_sanitize_version($checks->last_result->latest) : false;

if( isset( $checks->last_result->latest ) AND version_compare( $checks->last_result->latest, YOURLS_VERSION, '>' ) ) {
$msg = yourls_s( '<a href="%s">YOURLS version %s</a> is available. Please update!', 'http://yourls.org/download', $checks->last_result->latest );
if( $latest AND version_compare( $latest, YOURLS_VERSION, '>' ) ) {
$msg = yourls_s( '<a href="%s">YOURLS version %s</a> is available. Please update!', 'http://yourls.org/download', $latest );
yourls_add_notice( $msg );
}
}
Expand Down
26 changes: 25 additions & 1 deletion includes/functions-http.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ function yourls_check_core_version() {
// Parse response
$json = json_decode( trim( $req->body ) );

if( isset( $json->latest ) && isset( $json->zipurl ) ) {
if( yourls_validate_core_version_response($json) ) {
// All went OK - mark this down
$checks->failed_attempts = 0;
$checks->last_result = $json;
Expand All @@ -349,6 +349,30 @@ function yourls_check_core_version() {
return false;
}

/**
* Make sure response from api.yourls.org is valid
*
* we should get a json object with two following properties:
* 'latest' => a string representing a YOURLS version number, eg '1.2.3'
* 'zipurl' => a string for a zip package URL, from github, eg 'https://api.github.com/repos/YOURLS/YOURLS/zipball/1.2.3'
*
* @since 1.7.7
* @param $json JSON object to check
* @return bool true if seems legit, false otherwise
*/
function yourls_validate_core_version_response($json) {
return (
isset($json->latest)
&& isset($json->zipurl)
&& $json->latest === yourls_sanitize_version($json->latest)
&& $json->zipurl === yourls_sanitize_url($json->zipurl)
&& join('.',array_slice(explode('.',parse_url($json->zipurl, PHP_URL_HOST)), -2, 2)) === 'github.com'
// this last bit get the host ('api.github.com'), explodes on '.' (['api','github','com']) and keeps the last two elements
// to make sure domain is either github.com or one of its subdomain (api.github.com for instance)
// TODO: keep an eye on Github API to make sure it doesn't change some day to another domain (githubapi.com, ...)
);
}

/**
* Determine if we want to check for a newer YOURLS version (and check if applicable)
*
Expand Down
63 changes: 58 additions & 5 deletions tests/tests/http/api-check.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* HTTP functions related to api.yourls.org
*
* @group http
* @group AYO
* @since 0.1
*/
class HTTP_AYO_Tests extends PHPUnit_Framework_TestCase {
Expand Down Expand Up @@ -92,10 +93,6 @@ public function test_check_core_version() {
$check = yourls_check_core_version();
$after = yourls_get_option( 'core_version_checks' );

if( $check === false ) {
$this->markTestSkipped( 'api.yourls.org unreachable or broken' );
}

$this->assertNotSame( $before, $after );
$this->assertTrue( isset( $check->latest ) );
$this->assertTrue( isset( $check->zipurl ) );
Expand Down Expand Up @@ -280,7 +277,6 @@ public function case_scenario() {
* Check if we should poll api.yourls.org under various circumstances
*
* @dataProvider case_scenario
* @depends test_check_core_version
* @since 0.1
*/
public function test_api_check_in_various_scenario( $name, $checks, $expected ) {
Expand All @@ -292,4 +288,61 @@ public function test_api_check_in_various_scenario( $name, $checks, $expected )
$this->assertSame( $expected, yourls_maybe_check_core_version() );
}

/**
* Provide fake JSON responses from api.yourls.org and a boolean stating if they should be accepted or not
*/
public function json_responses() {
$return = array();

// expected
$return[] = array(
(object)array(
'latest' => '1.2.3',
'zipurl' => 'https://api.github.com/repos/YOURLS/YOURLS/zipball/1.2.3',
),
true);

// incorrect version number
$return[] = array(
(object)array(
'latest' => '1.2.3-something',
'zipurl' => 'https://api.github.com/repos/YOURLS/YOURLS/zipball/1.2.3',
),
false);

// url not part of github.com
$return[] = array(
(object)array(
'latest' => '1.2.3',
'zipurl' => 'https://notgithub.com/repos/YOURLS/YOURLS/zipball/1.2.3',
),
false);

// no version
$return[] = array(
(object)array(
'zipurl' => 'https://api.github.com/repos/YOURLS/YOURLS/zipball/1.2.3',
),
false);

// no URL
$return[] = array(
(object)array(
'latest' => '1.2.3',
),
false);

return $return;
}

/**
* Validate various json responses from api.yourls.org and make sure they're legit
*
* @dataProvider json_responses
* @since 0.1
*/
public function test_validate_api_json_response($json, $expected) {
$this->assertSame( $expected, yourls_validate_core_version_response($json) );
}

}

0 comments on commit 2bc2bb1

Please sign in to comment.