Issues (4967)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/wp-includes/cron.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * WordPress Cron API
4
 *
5
 * @package WordPress
6
 */
7
8
/**
9
 * Schedules an event to run only once.
10
 *
11
 * Schedules an event which will execute once by the WordPress actions core at
12
 * a time which you specify. The action will fire off when someone visits your
13
 * WordPress site, if the schedule time has passed.
14
 *
15
 * Note that scheduling an event to occur within 10 minutes of an existing event
16
 * with the same action hook will be ignored unless you pass unique `$args` values
17
 * for each scheduled event.
18
 *
19
 * @since 2.1.0
20
 * @link https://codex.wordpress.org/Function_Reference/wp_schedule_single_event
21
 *
22
 * @param int $timestamp Unix timestamp (UTC) for when to run the event.
23
 * @param string $hook Action hook to execute when event is run.
24
 * @param array $args Optional. Arguments to pass to the hook's callback function.
25
 * @return false|void False if the event does not get scheduled.
26
 */
27
function wp_schedule_single_event( $timestamp, $hook, $args = array()) {
28
	// Make sure timestamp is a positive integer
29
	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
30
		return false;
31
	}
32
33
	// Don't schedule a duplicate if there's already an identical event due within 10 minutes of it
34
	$next = wp_next_scheduled($hook, $args);
35
	if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) {
36
		return false;
37
	}
38
39
	$crons = _get_cron_array();
40
	$event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => false, 'args' => $args );
41
	/**
42
	 * Filters a single event before it is scheduled.
43
	 *
44
	 * @since 3.1.0
45
	 *
46
	 * @param stdClass $event {
47
	 *     An object containing an event's data.
48
	 *
49
	 *     @type string       $hook      Action hook to execute when event is run.
50
	 *     @type int          $timestamp Unix timestamp (UTC) for when to run the event.
51
	 *     @type string|false $schedule  How often the event should recur. See `wp_get_schedules()`.
52
	 *     @type array        $args      Arguments to pass to the hook's callback function.
53
	 * }
54
	 */
55
	$event = apply_filters( 'schedule_event', $event );
56
57
	// A plugin disallowed this event
58
	if ( ! $event )
59
		return false;
60
61
	$key = md5(serialize($event->args));
62
63
	$crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args );
64
	uksort( $crons, "strnatcasecmp" );
65
	_set_cron_array( $crons );
66
}
67
68
/**
69
 * Schedule a recurring event.
70
 *
71
 * Schedules a hook which will be executed by the WordPress actions core on a
72
 * specific interval, specified by you. The action will trigger when someone
73
 * visits your WordPress site, if the scheduled time has passed.
74
 *
75
 * Valid values for the recurrence are hourly, daily, and twicedaily. These can
76
 * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules().
77
 *
78
 * Use wp_next_scheduled() to prevent duplicates
79
 *
80
 * @since 2.1.0
81
 *
82
 * @param int $timestamp Unix timestamp (UTC) for when to run the event.
83
 * @param string $recurrence How often the event should recur.
84
 * @param string $hook Action hook to execute when event is run.
85
 * @param array $args Optional. Arguments to pass to the hook's callback function.
86
 * @return false|void False if the event does not get scheduled.
87
 */
88
function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) {
89
	// Make sure timestamp is a positive integer
90
	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
91
		return false;
92
	}
93
94
	$crons = _get_cron_array();
95
	$schedules = wp_get_schedules();
96
97
	if ( !isset( $schedules[$recurrence] ) )
98
		return false;
99
100
	$event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] );
101
	/** This filter is documented in wp-includes/cron.php */
102
	$event = apply_filters( 'schedule_event', $event );
103
104
	// A plugin disallowed this event
105
	if ( ! $event )
106
		return false;
107
108
	$key = md5(serialize($event->args));
109
110
	$crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args, 'interval' => $event->interval );
111
	uksort( $crons, "strnatcasecmp" );
112
	_set_cron_array( $crons );
113
}
114
115
/**
116
 * Reschedule a recurring event.
117
 *
118
 * @since 2.1.0
119
 *
120
 * @param int $timestamp Unix timestamp (UTC) for when to run the event.
121
 * @param string $recurrence How often the event should recur.
122
 * @param string $hook Action hook to execute when event is run.
123
 * @param array $args Optional. Arguments to pass to the hook's callback function.
124
 * @return false|void False if the event does not get rescheduled.
125
 */
126
function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
127
	// Make sure timestamp is a positive integer
128
	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
129
		return false;
130
	}
131
132
	$crons = _get_cron_array();
133
	$schedules = wp_get_schedules();
134
	$key = md5( serialize( $args ) );
135
	$interval = 0;
136
137
	// First we try to get it from the schedule
138
	if ( isset( $schedules[ $recurrence ] ) ) {
139
		$interval = $schedules[ $recurrence ]['interval'];
140
	}
141
	// Now we try to get it from the saved interval in case the schedule disappears
142
	if ( 0 == $interval ) {
143
		$interval = $crons[ $timestamp ][ $hook ][ $key ]['interval'];
144
	}
145
	// Now we assume something is wrong and fail to schedule
146
	if ( 0 == $interval ) {
147
		return false;
148
	}
149
150
	$now = time();
151
152
	if ( $timestamp >= $now ) {
153
		$timestamp = $now + $interval;
154
	} else {
155
		$timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
156
	}
157
158
	wp_schedule_event( $timestamp, $recurrence, $hook, $args );
159
}
160
161
/**
162
 * Unschedule a previously scheduled event.
163
 *
164
 * The $timestamp and $hook parameters are required so that the event can be
165
 * identified.
166
 *
167
 * @since 2.1.0
168
 *
169
 * @param int $timestamp Unix timestamp (UTC) for when to run the event.
170
 * @param string $hook Action hook, the execution of which will be unscheduled.
171
 * @param array $args Arguments to pass to the hook's callback function.
172
 * Although not passed to a callback function, these arguments are used
173
 * to uniquely identify the scheduled event, so they should be the same
174
 * as those used when originally scheduling the event.
175
 * @return false|void False if the event does not get unscheduled.
176
 */
177
function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
178
	// Make sure timestamp is a positive integer
179
	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
180
		return false;
181
	}
182
183
	$crons = _get_cron_array();
184
	$key = md5(serialize($args));
185
	unset( $crons[$timestamp][$hook][$key] );
186
	if ( empty($crons[$timestamp][$hook]) )
187
		unset( $crons[$timestamp][$hook] );
188
	if ( empty($crons[$timestamp]) )
189
		unset( $crons[$timestamp] );
190
	_set_cron_array( $crons );
0 ignored issues
show
It seems like $crons defined by _get_cron_array() on line 183 can also be of type false; however, _set_cron_array() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
191
}
192
193
/**
194
 * Unschedule all events attached to the specified hook.
195
 *
196
 * @since 2.1.0
197
 *
198
 * @param string $hook Action hook, the execution of which will be unscheduled.
199
 * @param array $args Optional. Arguments that were to be passed to the hook's callback function.
200
 */
201
function wp_clear_scheduled_hook( $hook, $args = array() ) {
202
	// Backward compatibility
203
	// Previously this function took the arguments as discrete vars rather than an array like the rest of the API
204
	if ( !is_array($args) ) {
205
		_deprecated_argument( __FUNCTION__, '3.0.0', __('This argument has changed to an array to match the behavior of the other cron functions.') );
206
		$args = array_slice( func_get_args(), 1 );
207
	}
208
209
	// This logic duplicates wp_next_scheduled()
210
	// It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing,
211
	// and, wp_next_scheduled() returns the same schedule in an infinite loop.
212
	$crons = _get_cron_array();
213
	if ( empty( $crons ) )
214
		return;
215
216
	$key = md5( serialize( $args ) );
217
	foreach ( $crons as $timestamp => $cron ) {
218
		if ( isset( $cron[ $hook ][ $key ] ) ) {
219
			wp_unschedule_event( $timestamp, $hook, $args );
220
		}
221
	}
222
}
223
224
/**
225
 * Retrieve the next timestamp for an event.
226
 *
227
 * @since 2.1.0
228
 *
229
 * @param string $hook Action hook to execute when event is run.
230
 * @param array $args Optional. Arguments to pass to the hook's callback function.
231
 * @return false|int The Unix timestamp of the next time the scheduled event will occur.
0 ignored issues
show
Should the return type not be false|integer|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
232
 */
233
function wp_next_scheduled( $hook, $args = array() ) {
234
	$crons = _get_cron_array();
235
	$key = md5(serialize($args));
236
	if ( empty($crons) )
237
		return false;
238
	foreach ( $crons as $timestamp => $cron ) {
239
		if ( isset( $cron[$hook][$key] ) )
240
			return $timestamp;
241
	}
242
	return false;
243
}
244
245
/**
246
 * Sends a request to run cron through HTTP request that doesn't halt page loading.
247
 *
248
 * @since 2.1.0
249
 *
250
 * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used).
251
 */
252
function spawn_cron( $gmt_time = 0 ) {
253
	if ( ! $gmt_time )
254
		$gmt_time = microtime( true );
255
256
	if ( defined('DOING_CRON') || isset($_GET['doing_wp_cron']) )
257
		return;
258
259
	/*
260
	 * Get the cron lock, which is a Unix timestamp of when the last cron was spawned
261
	 * and has not finished running.
262
	 *
263
	 * Multiple processes on multiple web servers can run this code concurrently,
264
	 * this lock attempts to make spawning as atomic as possible.
265
	 */
266
	$lock = get_transient('doing_cron');
267
268
	if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS )
269
		$lock = 0;
270
271
	// don't run if another process is currently running it or more than once every 60 sec.
272
	if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time )
273
		return;
274
275
	//sanity check
276
	$crons = _get_cron_array();
277
	if ( !is_array($crons) )
278
		return;
279
280
	$keys = array_keys( $crons );
281
	if ( isset($keys[0]) && $keys[0] > $gmt_time )
282
		return;
283
284
	if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
285
		if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) ||  defined( 'XMLRPC_REQUEST' ) ) {
286
			return;
287
		}
288
289
		$doing_wp_cron = sprintf( '%.22F', $gmt_time );
290
		set_transient( 'doing_cron', $doing_wp_cron );
291
292
		ob_start();
293
		wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
294
		echo ' ';
295
296
		// flush any buffers and send the headers
297
		while ( @ob_end_flush() );
298
		flush();
299
300
		WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' );
301
		return;
302
	}
303
304
	// Set the cron lock with the current unix timestamp, when the cron is being spawned.
305
	$doing_wp_cron = sprintf( '%.22F', $gmt_time );
306
	set_transient( 'doing_cron', $doing_wp_cron );
307
308
	/**
309
	 * Filters the cron request arguments.
310
	 *
311
	 * @since 3.5.0
312
	 * @since 4.5.0 The `$doing_wp_cron` parameter was added.
313
	 *
314
	 * @param array $cron_request_array {
315
	 *     An array of cron request URL arguments.
316
	 *
317
	 *     @type string $url  The cron request URL.
318
	 *     @type int    $key  The 22 digit GMT microtime.
319
	 *     @type array  $args {
320
	 *         An array of cron request arguments.
321
	 *
322
	 *         @type int  $timeout   The request timeout in seconds. Default .01 seconds.
323
	 *         @type bool $blocking  Whether to set blocking for the request. Default false.
324
	 *         @type bool $sslverify Whether SSL should be verified for the request. Default false.
325
	 *     }
326
	 * }
327
	 * @param string $doing_wp_cron The unix timestamp of the cron lock.
328
	 */
329
	$cron_request = apply_filters( 'cron_request', array(
330
		'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
331
		'key'  => $doing_wp_cron,
332
		'args' => array(
333
			'timeout'   => 0.01,
334
			'blocking'  => false,
335
			/** This filter is documented in wp-includes/class-wp-http-streams.php */
336
			'sslverify' => apply_filters( 'https_local_ssl_verify', false )
337
		)
338
	), $doing_wp_cron );
339
340
	wp_remote_post( $cron_request['url'], $cron_request['args'] );
341
}
342
343
/**
344
 * Run scheduled callbacks or spawn cron for all scheduled events.
345
 *
346
 * @since 2.1.0
347
 */
348
function wp_cron() {
349
	// Prevent infinite loops caused by lack of wp-cron.php
350
	if ( strpos($_SERVER['REQUEST_URI'], '/wp-cron.php') !== false || ( defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ) )
351
		return;
352
353
	if ( false === $crons = _get_cron_array() )
354
		return;
355
356
	$gmt_time = microtime( true );
357
	$keys = array_keys( $crons );
358
	if ( isset($keys[0]) && $keys[0] > $gmt_time )
359
		return;
360
361
	$schedules = wp_get_schedules();
362
	foreach ( $crons as $timestamp => $cronhooks ) {
363
		if ( $timestamp > $gmt_time ) break;
364
		foreach ( (array) $cronhooks as $hook => $args ) {
365
			if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
366
				continue;
367
			spawn_cron( $gmt_time );
368
			break 2;
369
		}
370
	}
371
}
372
373
/**
374
 * Retrieve supported event recurrence schedules.
375
 *
376
 * The default supported recurrences are 'hourly', 'twicedaily', and 'daily'. A plugin may
377
 * add more by hooking into the {@see 'cron_schedules'} filter. The filter accepts an array
378
 * of arrays. The outer array has a key that is the name of the schedule or for
379
 * example 'weekly'. The value is an array with two keys, one is 'interval' and
380
 * the other is 'display'.
381
 *
382
 * The 'interval' is a number in seconds of when the cron job should run. So for
383
 * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
384
 * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
385
 *
386
 * The 'display' is the description. For the 'weekly' key, the 'display' would
387
 * be `__( 'Once Weekly' )`.
388
 *
389
 * For your plugin, you will be passed an array. you can easily add your
390
 * schedule by doing the following.
391
 *
392
 *     // Filter parameter variable name is 'array'.
393
 *     $array['weekly'] = array(
394
 *         'interval' => 604800,
395
 *     	   'display'  => __( 'Once Weekly' )
396
 *     );
397
 *
398
 *
399
 * @since 2.1.0
400
 *
401
 * @return array
0 ignored issues
show
Consider making the return type a bit more specific; maybe use array<string,array<string,integer|string>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
402
 */
403
function wp_get_schedules() {
404
	$schedules = array(
405
		'hourly'     => array( 'interval' => HOUR_IN_SECONDS,      'display' => __( 'Once Hourly' ) ),
406
		'twicedaily' => array( 'interval' => 12 * HOUR_IN_SECONDS, 'display' => __( 'Twice Daily' ) ),
407
		'daily'      => array( 'interval' => DAY_IN_SECONDS,       'display' => __( 'Once Daily' ) ),
408
	);
409
	/**
410
	 * Filters the non-default cron schedules.
411
	 *
412
	 * @since 2.1.0
413
	 *
414
	 * @param array $new_schedules An array of non-default cron schedules. Default empty.
415
	 */
416
	return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
417
}
418
419
/**
420
 * Retrieve the recurrence schedule for an event.
421
 *
422
 * @see wp_get_schedules() for available schedules.
423
 *
424
 * @since 2.1.0
425
 *
426
 * @param string $hook Action hook to identify the event.
427
 * @param array $args Optional. Arguments passed to the event's callback function.
428
 * @return string|false False, if no schedule. Schedule name on success.
429
 */
430
function wp_get_schedule($hook, $args = array()) {
431
	$crons = _get_cron_array();
432
	$key = md5(serialize($args));
433
	if ( empty($crons) )
434
		return false;
435
	foreach ( $crons as $timestamp => $cron ) {
436
		if ( isset( $cron[$hook][$key] ) )
437
			return $cron[$hook][$key]['schedule'];
438
	}
439
	return false;
440
}
441
442
//
443
// Private functions
444
//
445
446
/**
447
 * Retrieve cron info array option.
448
 *
449
 * @since 2.1.0
450
 * @access private
451
 *
452
 * @return false|array CRON info array.
453
 */
454
function _get_cron_array()  {
455
	$cron = get_option('cron');
456
	if ( ! is_array($cron) )
457
		return false;
458
459
	if ( !isset($cron['version']) )
460
		$cron = _upgrade_cron_array($cron);
461
462
	unset($cron['version']);
463
464
	return $cron;
465
}
466
467
/**
468
 * Updates the CRON option with the new CRON array.
469
 *
470
 * @since 2.1.0
471
 * @access private
472
 *
473
 * @param array $cron Cron info array from _get_cron_array().
474
 */
475
function _set_cron_array($cron) {
476
	$cron['version'] = 2;
477
	update_option( 'cron', $cron );
478
}
479
480
/**
481
 * Upgrade a Cron info array.
482
 *
483
 * This function upgrades the Cron info array to version 2.
484
 *
485
 * @since 2.1.0
486
 * @access private
487
 *
488
 * @param array $cron Cron info array from _get_cron_array().
489
 * @return array An upgraded Cron info array.
490
 */
491
function _upgrade_cron_array($cron) {
492
	if ( isset($cron['version']) && 2 == $cron['version'])
493
		return $cron;
494
495
	$new_cron = array();
496
497
	foreach ( (array) $cron as $timestamp => $hooks) {
498
		foreach ( (array) $hooks as $hook => $args ) {
499
			$key = md5(serialize($args['args']));
500
			$new_cron[$timestamp][$hook][$key] = $args;
501
		}
502
	}
503
504
	$new_cron['version'] = 2;
505
	update_option( 'cron', $new_cron );
506
	return $new_cron;
507
}
508