CVE-2026-56700: Verified Reproduction
CVE-2026-56700: Grav CMS unsafe deserialization and command injection RCE
CVE-2026-56700 is verified against the affected target. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00233.
What Is CVE-2026-56700?
CVE-2026-56700 is a critical unsafe-deserialization vulnerability in Grav CMS's modern scheduler job queue, letting a forged serialized scheduler Job object execute an attacker-selected command when scheduler processing is triggered. Pruva reproduced it (reproduction REPRO-2026-00233).
CVE-2026-56700 Severity & CVSS Score
CVE-2026-56700 is rated critical severity, with a CVSS base score of 9.8 out of 10.
Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.
How to Reproduce CVE-2026-56700
pruva-verify REPRO-2026-00233 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00233/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-56700
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
forged scheduler queue JSON file containing a base64 serialized Grav\Common\Scheduler\Job object; remote trigger is POST /scheduler/webhook
- POST /scheduler/webhook
- Scheduler::processWebhookTrigger()
- Scheduler::run()
- JobQueue::reconstructJob()
- unserialize(serialized_job)
- Job::run/system
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-56700
- Affected versions: Grav CMS versions before 2.0.0-beta.2. The reproduction uses 2.0.0-beta.1 as the vulnerable version and 2.0.0-beta.2 as the fixed negative control.
- Risk level and consequences: critical. If an attacker can place or tamper with a scheduler queue item and trigger scheduler processing, the queue deserialization path can instantiate a forged scheduler
Joband execute arbitrary commands in the PHP/Grav process context.
Impact Parity
- Disclosed/claimed maximum impact: remote/API-triggered arbitrary code execution through unsafe deserialization in Grav components, including
Scheduler\JobQueue. - Reproduced impact from this run: code execution. The proof crafts real serialized
Grav\Common\Scheduler\Jobpayloads whose command writes marker files, starts a real Grav web server with the real scheduler-webhook plugin, and sendsPOST /scheduler/webhookto triggerScheduler::processWebhookTrigger()->Scheduler::run()->JobQueue::popWithId()/reconstructJob(). - Parity:
full. - Not demonstrated: the reproduction focuses on the
Scheduler\JobQueuevector. It does not separately exploit theFileCacheorSession::getFlashObjectunsafe unserialize sinks.
Root Cause
The vulnerable JobQueue::reconstructJob() path trusted the on-disk queue item field serialized_job and directly performed:
$job = unserialize(base64_decode((string) $item['serialized_job']));
No HMAC, signature, or class restriction prevented an attacker-planted/tampered queue item from supplying a serialized Grav\Common\Scheduler\Job. The Job object has an execution path that invokes its configured command/arguments, so a forged serialized job with command system and attacker-controlled arguments becomes a direct PHP object injection to command execution primitive.
The fixed version signs the serialized job blob with an HMAC derived from Grav's nonce key and only unserializes when the sibling serialized_job_hmac verifies. Missing or mismatched HMAC values fall through to the structured queue fields instead of trusting the serialized object. The advisory identifies the fix as Grav core commit c66dfeb5f for JobQueue/FileCache/Session/InstallCommand hardening, released in 2.0.0-beta.2.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.sh. - The script reuses/clones the real Grav repository, checks out 2.0.0-beta.1 and 2.0.0-beta.2, installs Composer dependencies, installs/enables the real
scheduler-webhookplugin, starts the real PHP/Grav web server, poisons the real scheduler queue with a forgedserialized_job, and sendsPOST /scheduler/webhookto trigger scheduler processing over HTTP. - Expected evidence: vulnerable 2.0.0-beta.1 creates
bundle/repro/proof_vulnerable_1.txtandbundle/repro/proof_vulnerable_2.txt; fixed 2.0.0-beta.2 does not create fixed proof files and logs execution of the benign/bin/truefallback job instead.
Evidence
- Runtime manifest:
bundle/repro/runtime_manifest.jsonrecordsentrypoint_kind="api_remote",service_started=true,healthcheck_passed=true, andtarget_path_reached=true. - Structured verdict:
bundle/repro/validation_verdict.jsonrecordsclaim_outcome="confirmed",validated_surface="api_remote", andobserved_impact_class="code_execution". - Vulnerable proof files:
bundle/repro/proof_vulnerable_1.txtcontainsGRAV_JOBQUEUE_WEBHOOK_RCE_vulnerable_1.bundle/repro/proof_vulnerable_2.txtcontainsGRAV_JOBQUEUE_WEBHOOK_RCE_vulnerable_2.
- Vulnerable HTTP evidence:
bundle/logs/vulnerable_webhook_response_1_body.jsonshows the webhook returned success andjobs_run: 1.bundle/logs/vulnerable_scheduler_1.logandbundle/logs/vulnerable_scheduler_2.logshow the forged job completed successfully with commandsystem.
- Fixed negative control:
bundle/logs/fixed_scheduler_1.logandbundle/logs/fixed_scheduler_2.logshow the fixed version completed the benign fallback job (/bin/true) rather than the attacker-controlled serializedJob.- No
proof_fixed_*.txtfiles are produced.
- Patch-gap evidence:
bundle/logs/vulnerable_jobqueue_gap.logcontains the vulnerable unsignedunserialize(base64_decode(...))sink.bundle/logs/fixed_jobqueue_gap.logcontains the HMAC validation logic added in the fixed version.
- Environment details:
- Grav vulnerable tag: 2.0.0-beta.1 (
26a2d519c59c620e2b0a54d0baf33889d7d5db0a). - Grav fixed tag: 2.0.0-beta.2 (
f95b0ff51a655edcbcc060a3d74b43e3f20b9585). - Scheduler-webhook plugin commit used for the HTTP endpoint: recorded in
bundle/logs/webhook_plugin_commit.log.
- Grav vulnerable tag: 2.0.0-beta.1 (
Recommendations / Next Steps
- Upgrade Grav CMS to 2.0.0-beta.2 or later.
- Preserve HMAC/integrity validation for every serialized queue/cache/session payload and reject or safely rebuild unsigned legacy data rather than unserializing it.
- Prefer avoiding PHP object serialization for attacker-influenced persistent data. If serialization is unavoidable, use strict integrity checks, narrow
allowed_classes, and schema-based reconstruction. - Add regression tests that insert an unsigned/tampered queue item with a serialized
Joband assert that the scheduler does not execute it. - Review other flat-file write paths to ensure untrusted users cannot create scheduler queue, cache, or session payloads.
Additional Notes
- Idempotency confirmation:
bundle/repro/reproduction_steps.shwas executed twice consecutively and produced the same vulnerable/fixed divergence both times. - The proof uses the real Grav product, real Composer dependencies, real scheduler-webhook plugin, real local HTTP requests, and real
JobQueue::reconstructJob()deserialization. It does not mock Grav classes or reimplement the sink. - The queue-file placement models the advisory precondition for the JobQueue vector: attacker-planted or tampered queue data. The remote/API boundary is the real webhook trigger that causes the product to process that queue item.
CVE-2026-56700 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.
Artifacts and Evidence for CVE-2026-56700
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-56700
FAQ: CVE-2026-56700
What access does an attacker need to exploit CVE-2026-56700?
Are other Grav components affected besides the scheduler job queue?
How severe is CVE-2026-56700?
How can I reproduce CVE-2026-56700?
References for CVE-2026-56700
Authoritative sources for CVE-2026-56700 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.