CVE-2026-86827: BackWPup Unauthenticated Backup Job Execution via WP-Cron
A missing authorization boundary in BackWPup cronrun allowed unauthenticated requests to start existing backup jobs. Includes source analysis, local runtime validation and a negative control.
CVE-2026-86827: BackWPup Unauthenticated Backup Job Execution via WP-Cron
Overview
CVE-2026-86827 is a missing authorization vulnerability in BackWPup, a WordPress backup and restore plugin. Its cron-triggered execution path accepted unauthenticated HTTP requests and could start an existing backup job immediately, regardless of the administrator’s configured schedule.
I identified the underlying issue while reviewing the plugin’s WP-Cron execution handler, then reproduced it on a local WordPress installation running BackWPup 5.7.5. A fresh, unauthenticated cURL request launched an existing database backup job and produced a 107,008-byte backup archive.
The public advisory identifies affected versions as 3.3 through 5.7.6, with the issue fixed in 5.7.7. The official changelog credits Duy Tran for reporting the issue.
Summary
| Field | Details |
|---|---|
| CVE | CVE-2026-86827 |
| Product | BackWPup – WordPress Backup & Restore Plugin |
| Affected versions (public advisory) | 3.3–5.7.6 |
| Runtime-validated version | 5.7.5 |
| Fixed version | 5.7.7 |
| Weakness | CWE-862 – Missing Authorization |
| Severity | Medium |
| CVSS v3.1 | 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N) |
| Authentication required | None |
| Researcher | Duy Tran (MrDarkRoot) |
| WPScan vulnerability ID | c7785a5b-f580-416f-a23d-58c28c717b60 |
The attacker does not gain demonstrated access to backup archives or the ability to create jobs or configure backup destinations. The demonstrated security violation is unauthorized execution of existing jobs.
Expected Behavior
Scheduled backup jobs should run only under their configured trigger conditions. Manual execution should require an authorized user or a properly authenticated external integration. An HTTP request to WordPress’s publicly reachable cron entry point should not be sufficient proof that the caller is WordPress’s trusted scheduler.
Actual Behavior
BackWPup’s cronrun path replaced the expected nonce with an empty string. The request parser also allowed an empty nonce value. As a result, the subsequent equality check could pass without a secret, authentication cookie, API key or authorization check.
The handler then called the backup job execution function directly.
Vulnerability Chain
1. The cronrun mode nullifies its own nonce check
The relevant logic from inc/class-cron.php, as recorded during the original review, was:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$args = array_merge(
[
'run' => '',
'nonce' => '',
'jobid' => 0,
],
$args
);
$nonce = substr(
wp_hash( wp_nonce_tick() . 'backwpup_job_run-' . $args['run'], 'nonce' ),
-12,
10
);
if ( 'cronrun' === $args['run'] ) {
$nonce = '';
}
if ( $nonce !== $args['nonce'] ) {
return;
}
The normal nonce derivation is discarded specifically for cronrun. When the supplied nonce is empty, both sides of the comparison are '', so the request is not rejected. This is not cryptographic nonce forgery: it is an authorization design flaw in which the check deliberately compares two empty values.
2. The accepted request reaches backup execution
The same handler proceeds to:
1
BackWPup_Job::start_http( $args['run'], $args['jobid'] );
In the reviewed path, there was no corresponding current_user_can() gate or independently authenticated internal-scheduler origin check before this call.
For contrast, the plugin’s REST job-start route used a permission callback:
1
2
3
'permission_callback' => function () {
return current_user_can( Capability::JOBS_START );
},
The discrepancy matters: the same sensitive operation had a capability boundary in one interface but not in the cron execution path.
3. Publicly reachable cron processing crosses the trust boundary
The WordPress wp-cron.php entry point is ordinarily reachable over HTTP. In the tested BackWPup version, attacker-controlled query parameters reached the plugin’s cron handler without a logged-in WordPress session.
The effective flow was:
1
2
3
4
5
6
7
Unauthenticated HTTP request
-> WordPress wp-cron.php
-> BackWPup cronrun processing
-> expected nonce forced to empty string
-> empty supplied nonce accepted
-> BackWPup_Job::start_http()
-> existing backup job executes
The broken invariant was: the ability to reach a cron execution handler is not authorization to run a privileged backup job.
Required Conditions / Attack Preconditions
The lab scenario required BackWPup to be installed, an existing backup job with a known job ID, and the vulnerable handler to be reachable. The attacker did not need a WordPress account, a valid session cookie, a BackWPup API key or additional HTTP headers.
The finding does not prove arbitrary job creation, arbitrary file download, or database disclosure to the remote caller.
Technical Validation
I reproduced the issue on an isolated local staging environment:
| Property | Test environment |
|---|---|
| WordPress | 6.8.3 |
| BackWPup | 5.7.5 |
| PHP | 8.2 |
| Target | Localhost (127.0.0.1:8080) |
| Authentication | None |
| Existing job | Job ID 1, database backup |
Initial state
Before the test:
- Job 1 existed with
active_type=wpcron. - No job was running (
working=false). - The backup directory contained no archives.
- The log directory contained no BackWPup job log files.
- The HTTP client did not send WordPress cookies or authentication headers.
Positive test: unauthenticated job execution
On the local, researcher-controlled test installation, I issued:
1
curl -sS -i "http://127.0.0.1:8080/wp-cron.php?backwpup_run=cronrun&jobid=1&_nonce="
The HTTP response was 200 OK. This status alone does not prove backup execution; the server-side artifacts do.
After processing, BackWPup created a job log and a 107,008-byte database backup archive under its uploads directory. The local execution marker .backwpup_job_started contained cronrun.
A redacted log excerpt showed:
1
2
3
4
5
[INFO] BackWPup job: Runtime DB Job 1
[2026-09-07 01:59:42 UTC] 1. Try to backup database
[2026-09-07 01:59:42 UTC] Connected to database wordpress on db:3306
[2026-09-07 01:59:42 UTC] Added database dump "wordpress.sql"
[2026-09-07 01:59:42 UTC] Database backup done!
These observations establish that the request caused a real backup operation, not merely an HTTP response or the creation of an empty marker.
Negative control: rejected runext nonce
I separately tested the runext mode with an invalid nonce:
1
curl -sS -i "http://127.0.0.1:8080/wp-cron.php?backwpup_run=runext&jobid=1&_nonce=INVALID"
This request also returned 200 OK, but did not create another backup log, and the number of logs remained unchanged. No additional job execution was observed.
This control is important because it distinguishes a successful HTTP request from an authorized backup operation and isolates the weak boundary to the cronrun path.
Trust-Boundary Analysis
The vulnerability was not simply that wp-cron.php was publicly accessible. Public cron entry points are part of ordinary WordPress operation.
The security problem arose when BackWPup treated an HTTP request selecting cronrun as sufficient authority to run a specific existing job.
The path conflated two separate properties:
- A request can reach the WordPress cron handler.
- A request is authorized to invoke an internal scheduled backup operation.
Only the first was established. The second was effectively assumed.
A meaningful authorization design must verify the operation’s trusted execution context and enforce the job’s permitted scheduling or manual-start rules, not rely on a user-supplied mode plus an empty nonce.
Impact
The observed impact was unauthorized immediate execution of an existing database backup job.
Additional risks depend on the configured job and hosting environment:
- CPU, memory and disk I/O consumption from unexpectedly triggered backup processing.
- Disk-space pressure from repeated backup generation where retention and concurrency controls permit it.
- Network usage where an existing job uploads an archive to a configured remote destination.
- Operational interference with normal backup scheduling.
Potential resource exhaustion is a plausible consequence, not a denial-of-service outcome demonstrated by this PoC. Likewise, archive theft, remote code execution, and configuration changes were not demonstrated.
The published CVSS assessment is 5.3 (Medium).
Remediation
BackWPup resolved the issue in version 5.7.7, released October 5, 2026. Administrators should update to 5.7.7 or later.
The vendor’s changelog records the security fix as preventing scheduled backup jobs from being triggered by unauthenticated requests and credits Duy Tran.
Secure Design Recommendations
- Keep internal scheduler authorization distinct from request parameters and public endpoint reachability.
- Do not use a hardcoded empty nonce as proof of internal scheduler origin.
- Validate whether the targeted job is authorized to execute under the requested trigger and schedule.
- Require appropriate capabilities or authenticated integration credentials for externally initiated manual operations.
- Add negative tests confirming that unauthenticated external requests cannot execute backup jobs.
- Apply concurrency limits and monitor unexpected execution frequency as defense in depth.
Checking DOING_CRON alone is not a sufficient security fix: normal public wp-cron.php execution can also set that constant. A robust solution must establish the actual trusted invocation or authorization boundary.
Disclosure Timeline
| Date | Event |
|---|---|
| September 7, 2026 | Local runtime evidence recorded in the original report |
| October 5, 2026 | BackWPup 5.7.7 released with a credited security fix |
| October 6, 2026 | WPScan vulnerability publication date |
| October 8, 2026 | CVE-2026-86827 published in the CVE/NVD ecosystem |
| October 12, 2026 | This technical write-up prepared for publication |
The original submission date and any private vendor correspondence are not reproduced here.
Research Credit
Discovered and reported by Duy Tran (MrDarkRoot).
The evidence described in this article comes from my isolated local test environment and the original vulnerability report. The affected-version range and fixed version are taken from public advisory metadata rather than inferred from testing every historical release.
References
- WPScan vulnerability record
- CVE-2026-86827 on NVD
- BackWPup official WordPress.org changelog
- Patchstack vulnerability record
Responsible Disclosure Notice
The demonstrated requests target an isolated localhost installation and are included solely to document a publicly disclosed, fixed vulnerability. Do not test third-party installations without authorization. Site administrators should update to the patched version rather than rely on endpoint filtering alone.