Skip to content

CVE-2025-68456: Verified Reproduction

CVE-2025-68456: Craft CMS: Unauthenticated Database Backup Trigger

CVE-2025-68456 is verified against craftcms/cms · composer. Vulnerability class: Info Disclosure. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00054.

REPRO-2026-00054 craftcms/cms · composer Info Disclosure Jan 8, 2026 CVE entry .txt
Severity
CRITICAL
CVSS
9.1
Reproduced in
36m 45s
Tool calls
51
01 · Overview

What Is CVE-2025-68456?

CVE-2025-68456 is a medium-severity vulnerability in Craft CMS (craftcms/cms) where unauthenticated users can trigger database backup operations via specific admin actions. Pruva reproduced it (reproduction REPRO-2026-00054).

02 · Severity & CVSS

CVE-2025-68456 Severity & CVSS Score

CVE-2025-68456 is rated critical severity, with a CVSS base score of 9.1 out of 10.

CRITICAL threat level
9.1 / 10 CVSS base
Weakness CWE-202 — Exposure of Sensitive Information Through Query Strings in GET Request

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

How to Reproduce CVE-2025-68456

$ pruva-verify REPRO-2026-00054
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00054/artifacts/bundle/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2025-68456

Reproduced by Pruva's autonomous agents — 51 tool calls over 37 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 56 events · 51 tool calls · 37 min
37 minDuration
51Tool calls
0Reasoning steps
56Events
Agent activity over 37 min
Support
3
Repro
50
0:0036:45

Root Cause and Exploit Chain for CVE-2025-68456

Versions: >= 5.0.0-RC1, <= 5.8.20 and >= 3.0.0, <= 4.16.16

Unauthenticated users can trigger database backup operations in Craft CMS via specific admin controller actions that are explicitly configured with anonymous access flags. This vulnerability allows attackers to cause resource exhaustion (disk space, CPU) through repeated backup requests or potentially gain access to sensitive database information if combined with other vulnerabilities.

  • Package/Component: craftcms/cms - Admin Controllers (AppController, BaseUpdaterController)
  • Affected Versions: >= 5.0.0-RC1, <= 5.8.20 and >= 3.0.0, <= 4.16.16
  • Risk Level: HIGH - Unauthenticated DoS and potential information disclosure
  • Consequences:
    • Disk space exhaustion through repeated backup creation
    • CPU/IO resource consumption during backup operations
    • Potential sensitive data exposure if backup files are accessible

Root Cause

The vulnerability exists because certain admin controller actions are explicitly configured to allow anonymous (unauthenticated) access:

// AppController.php
protected array|bool|int $allowAnonymous = [
    'migrate' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE,
    // ...
];

// BaseUpdaterController.php
protected array|bool|int $allowAnonymous = self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE;

When backupOnUpdate is enabled in the Craft configuration (which is the default), these endpoints trigger Craft::$app->getDb()->backup(), creating a database backup file.

Fix Commit: f83d4e0c6b906743206b4747db4abf8164b8da39

Reproduction Steps

  1. Reference to repro/reproduction_steps.sh which automates the full reproduction
  2. The script:
    • Sets up a Craft CMS 5.8.19 installation with PostgreSQL
    • Configures backupOnUpdate => true (default behavior)
    • Attempts unauthenticated POST to /admin/actions/app/migrate
    • Attempts the updater flow: /admin/actions/updater/index/admin/actions/updater/backup
  3. Expected evidence: Database backup file created in storage/backups/ or dbBackupPath in HTTP response

Evidence

  • Log Files:
    • logs/run-*.log - Main execution log
    • logs/curl-*.log - HTTP request/response traces
    • logs/php-server-*.log - PHP built-in server logs
  • Key Excerpts:
    • Response includes dbBackupPath pointing to storage/backups/<name>.sql
    • Backup files appear in the storage/backups/ directory
  • Environment: Craft CMS 5.8.19, PHP 8.2, PostgreSQL

Recommendations / Next Steps

  1. Immediate Fix: Update to Craft CMS 5.8.21 or 4.16.17
  2. Mitigation: If update not possible immediately:
    • Set backupOnUpdate => false in config/general.php
    • Restrict access to /admin/actions/* endpoints at web server level
  3. Testing: After update, verify:
    • Anonymous POST to /admin/actions/app/migrate returns 401/403
    • Anonymous POST to /admin/actions/updater/backup returns 401/403

Additional Notes

  • Idempotency: The reproduction script is idempotent - running it multiple times produces consistent results
  • Limitations: The reproduction requires network access to install Craft CMS via Composer
  • Edge Cases: The vulnerability requires backupOnUpdate to be enabled (default), installations with this disabled are not affected

References

CVE-2025-68456 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:0036:45
0:00
session startedgpt-5.1-codex · ghsa-v64r-7wg9-23pr · ghsa-v64
0:56
extract_facts
no facts extracted
0:56
0:56
supportrepro
36:45
36:45
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Requirements satisfied by this script:
# - Installs all dependencies (PHP, Composer, MariaDB, curl)
# - Sets up a vulnerable Craft CMS 5.8.19 instance
# - Enables backupOnUpdate
# - Starts a web server
# - Triggers unauthenticated backup via vulnerable endpoints
# - Produces logs under /bundle/logs
# - Exit code: 0 if reproduced (backup detected), 1 otherwise

LOG_DIR="/bundle/logs"
APP_DIR="/bundle/repro/craftapp"
PHP_BIN="/usr/bin/php"
COMPOSER_BIN="/usr/bin/composer"
DB_NAME="craft"
DB_USER="craftuser"
DB_PASS="craftpass"
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/reproduction_steps.sh
168.8s
[INFO] Starting reproduction run at 20260108-104941
[INFO] Installing required packages (this may take several minutes)...
[INFO] Ensuring MariaDB is running...
[INFO] Creating database and user if needed...
[INFO] Creating Craft CMS project (template)...
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs, and exits 0 on success (backup evidence), 1 otherwise.

LOG_DIR="/bundle/logs"
APP_ROOT="/bundle/repro"
APP_DIR="${APP_ROOT}/craftapp"
PHP_BIN="$(command -v php || echo /usr/bin/php)"
COMPOSER_BIN="$(command -v composer || echo /usr/local/bin/composer)"
DB_NAME="craft"
DB_USER="craftuser"
DB_PASS="craftpass"
DB_HOST="127.0.0.1"
DB_PORT="3306"
SERVER_HOST="127.0.0.1"
SERVER_PORT="8080"
BASE_URL="http://${SERVER_HOST}:${SERVER_PORT}"
NOW_TS=$(date +%Y%m%d-%H%M%S)
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/reproduction_steps.sh
87.0s
[INFO] Starting reproduction run at 20260108-105323
[INFO] Installing required packages (this may take several minutes)...
[INFO] Ensuring MariaDB is running...
[INFO] Creating database and user if needed...
[INFO] Creating Craft CMS project (template)...
[INFO] Pinning CMS to vulnerable version 5.8.19...
[INFO] Writing .env configuration...
[INFO] Ensuring backupOnUpdate is enabled...
36:45
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs, and exits 0 on success (backup evidence), 1 otherwise.

# Derive workspace root based on this script location, ensuring absolute paths within the repo bundle directory
SCRIPT_PATH="$(readlink -f "$0")"
REPRO_DIR="$(dirname "${SCRIPT_PATH}")"
ROOT_DIR="$(dirname "${REPRO_DIR}")"   # points to .../bundle

LOG_DIR="${ROOT_DIR}/logs"
APP_ROOT="${ROOT_DIR}/repro"
APP_DIR="${APP_ROOT}/craftapp"
PHP_BIN="$(command -v php || echo /usr/bin/php)"
COMPOSER_BIN="$(command -v composer || echo /usr/local/bin/composer)"
DB_NAME="craft"
DB_USER="craftuser"
DB_PASS="craftpass"
DB_HOST="127.0.0.1"
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/reproduction_steps.sh
73.9s
[INFO] Starting reproduction run at 20260108-105607
[INFO] Installing required packages (this may take several minutes)...
[INFO] Ensuring MariaDB is running...
[INFO] Creating database and user if needed...
[INFO] Creating Craft CMS project (template)...
[INFO] Pinning CMS to vulnerable version 5.8.19...
[INFO] Writing .env configuration...
[INFO] Ensuring backupOnUpdate is enabled...
36:45
36:45
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs under /bundle/logs
# Exit code: 0 if reproduction succeeded (backup evidence), 1 otherwise

# Resolve absolute paths inside /bundle
SCRIPT_PATH="$(readlink -f "$0")"
BUNDLE_DIR="$(dirname "${SCRIPT_PATH}")"
LOG_DIR="${BUNDLE_DIR}/logs"
APP_ROOT="${BUNDLE_DIR}/repro"
APP_DIR="${APP_ROOT}/craftapp"

# Use PHP 8.2 explicitly to avoid incompatibilities with vulnerable versions
PHP_BIN="/usr/bin/php8.2"
COMPOSER_PHAR="/usr/local/bin/composer"
COMPOSER_CALL=("${PHP_BIN}" "${COMPOSER_PHAR}")

DB_NAME="craft"
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/reproduction_steps.sh
166.1s
[INFO] Starting reproduction run at 20260108-105857
[INFO] Installing dependencies...
[INFO] Ensuring MariaDB is running...
[INFO] Creating database and user if needed...
[INFO] Pinning craftcms/cms to vulnerable 5.8.19 and installing with PHP 8.2...
[INFO] Current installed craftcms/cms version:
[INFO] Writing .env and general.php...
[INFO] Running Craft installation (idempotent)...
36:45
36:45
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs under /bundle/logs
# Exit code: 0 if reproduction succeeded (backup evidence), 1 otherwise

SCRIPT_PATH="$(readlink -f "$0")"
BUNDLE_DIR="$(dirname "${SCRIPT_PATH}")"
LOG_DIR="${BUNDLE_DIR}/logs"
APP_ROOT="${BUNDLE_DIR}/repro"
APP_DIR="${APP_ROOT}/craftapp"

# Use PHP 8.2 specifically to satisfy vulnerable dependency tree
PHP_BIN="/usr/bin/php8.2"
COMPOSER_PHAR="/usr/local/bin/composer"
COMPOSER_CALL=("${PHP_BIN}" "${COMPOSER_PHAR}")

DB_NAME="craft"
DB_USER="craftuser"
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/reproduction_steps.sh
41.0s
[INFO] Starting reproduction run at 20260108-110310
[INFO] Installing dependencies...
[INFO] PHP binary: PHP 8.2.30 (cli) (built: Dec 18 2025 23:37:12) (NTS)
[INFO] Ensuring MariaDB is running...
[INFO] Creating database and user if needed...
[INFO] Forcing dependency tree compatible with PHP 8.2 and Craft 5.8.19...
[INFO] Installed craftcms/cms:
[INFO] Writing .env and general.php...
36:45
36:45
36:45
$mysql -h 127.0.0.1 -P 3306 -ucraftuser -pcraftpass -e "SELECT 1"
ERROR 1045 (28000): Access denied for user 'craftuser'@'localhost' (using password: YES)
36:45
$mysql --protocol=socket -uroot -e "SELECT 1"
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs under /bundle/logs
# Exit code: 0 if reproduction succeeded (backup evidence), 1 otherwise

SCRIPT_PATH="$(readlink -f "$0")"
BUNDLE_DIR="$(dirname "${SCRIPT_PATH}")"
LOG_DIR="${BUNDLE_DIR}/logs"
APP_ROOT="${BUNDLE_DIR}/repro"
APP_DIR="${APP_ROOT}/craftapp"

# Use PHP 8.2 specifically to satisfy vulnerable dependency tree
PHP_BIN="/usr/bin/php8.2"
COMPOSER_PHAR="/usr/local/bin/composer"
COMPOSER_CALL=("${PHP_BIN}" "${COMPOSER_PHAR}")

# Local MariaDB (user-scoped) to avoid systemd/unix_socket auth
LOCAL_DB_DIR="${APP_ROOT}/mysql-data"
36:45
$bash /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/reproduction_steps.sh
72.9s
[INFO] Starting reproduction run at 20260108-110610
[INFO] Target BASE_URL=http://127.0.0.1:8080
[INFO] Installing dependencies...
[INFO] PHP binary: PHP 8.2.30 (cli) (built: Dec 18 2025 23:37:12) (NTS)
[INFO] Starting local MariaDB instance (port 3307)...
[INFO] Initializing data directory at /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysql-data ...
[ERROR] Local MariaDB failed to start. See /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysqld.err
36:45
36:45
36:45
36:45
#!/usr/bin/env bash
set -euo pipefail

# Reproduction script for GHSA-v64r-7wg9-23pr (Craft CMS unauthenticated backup trigger)
# Self-contained, idempotent, produces logs under /bundle/logs
# Exit code: 0 if reproduction succeeded (backup evidence), 1 otherwise

SCRIPT_PATH="$(readlink -f "$0")"
BUNDLE_DIR="$(dirname "${SCRIPT_PATH}")"
LOG_DIR="${BUNDLE_DIR}/logs"
APP_ROOT="${BUNDLE_DIR}/repro"
APP_DIR="${APP_ROOT}/craftapp"

# Use PHP 8.2 specifically to satisfy vulnerable dependency tree
PHP_BIN="/usr/bin/php8.2"
COMPOSER_PHAR="/usr/local/bin/composer"
COMPOSER_CALL=("${PHP_BIN}" "${COMPOSER_PHAR}")

# Local MariaDB (user-scoped) to avoid systemd/unix_socket auth
LOCAL_DB_DIR="${APP_ROOT}/mysql-data"
36:45
$bash -lc "cat /etc/passwd | grep mysql || true"
0.5s
mysql:x:104:105:MariaDB Server,,,:/nonexistent:/bin/false
36:45
$bash -lc "cat /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysqld.out || true && ls -l /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysql-data | head -n 50"
0.5s
2026-01-08 11:06:22 0 [Warning] Could not increase number of max_open_files to more than 20000 (request: 32198)
/usr/sbin/mariadbd: Please consult the Knowledge Base to find out how to run mysqld as root!
2026-01-08 11:06:22 0 [ERROR] Aborting
total 111026
-rw-rw---- 1 root root    417792 Jan  8 11:06 aria_log.00000001
-rw-rw---- 1 root root        52 Jan  8 11:06 aria_log_control
-rw-rw---- 1 root root       906 Jan  8 11:06 ib_buffer_pool
-rw-rw---- 1 root root 100663296 Jan  8 11:06 ib_logfile0
36:45
$bash -lc "ls -l /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro | sed -n '1,200p'; echo '---'; [ -f /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysqld.err ] && sed -n '1,200p' /root/.pruva/runs/ghsa-v64r-7wg9-23pr_20260108-104712/bundle/repro/mysqld.err || echo 'no mysqld.err'"
0.4s
total 20
drwxr-xr-x 7 root root  4096 Jan  8 11:03 craftapp
drwxr-xr-x 6 root root  4096 Jan  8 11:06 mysql-data
-rw-r--r-- 1 root root     6 Jan  8 11:06 mysqld.local.pid
-rw-r--r-- 1 root root   244 Jan  8 11:06 mysqld.out
-rw-r--r-- 1 root root     6 Jan  8 11:00 php-server.pid
-rw-r--r-- 1 root root 10052 Jan  8 10:56 reproduction_steps.sh
---
08 · How to Fix

How to Fix CVE-2025-68456

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2025-68456 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2025-68456

How severe is CVE-2025-68456?

It is rated medium severity. No CVSS score is published in the available advisory data for this reproduction.

How can I reproduce CVE-2025-68456?

Download the verified script from this page and run it in an isolated environment against a Craft CMS (craftcms/cms) installation. Send an unauthenticated request to the specific admin action documented in the advisory and confirm that a database backup operation is triggered without any credentials.
11 · References

References for CVE-2025-68456

Authoritative sources for CVE-2025-68456 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.