Skip to content

CVE-2026-57518: Verified Repro With Script Download

CVE-2026-57518: Pagekit CMS privilege escalation leading to RCE

CVE-2026-57518 is verified against pagekit/pagekit · github. Affected versions: <= 1.0.18. Fixed in None available; project archived. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00256.

REPRO-2026-00256 pagekit/pagekit · github RCE Variant found Jul 6, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.8
Confidence
HIGH
Reproduced in
23m 15s
Tool calls
291
Spend
$6.60
01 · Overview

What Is CVE-2026-57518?

CVE-2026-57518 is a high-severity privilege escalation vulnerability in Pagekit CMS 1.0.18 and earlier that lets an authenticated low-privileged user escalate to admin-level permissions and ultimately achieve remote code execution. Pruva reproduced it (reproduction REPRO-2026-00256).

02 · Severity & CVSS

CVE-2026-57518 Severity & CVSS Score

CVE-2026-57518 is rated high severity, with a CVSS base score of 8.8 out of 10.

HIGH threat level
8.8 / 10 CVSS base
Weakness CWE-862 Missing Authorization / CWE-269 Improper Privilege Management — Missing Authorization

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected pagekit/pagekit Versions

pagekit/pagekit · github versions <= 1.0.18 are affected.

How to Reproduce CVE-2026-57518

$ pruva-verify REPRO-2026-00256
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00256/artifacts/bundle/repro/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-2026-57518

Remote code execution — reproduced
  • 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
Trigger

authenticated low-privileged user with 'user: manage users' permission self-assigns a custom role with 'system: manage packages' via POST /api/user/{id}, then uploads and installs a malicious PHP package

Attack chain
  1. POST /api/user/{id} with roles array containing custom role ID (not 3)
  2. POST /admin/system/package/upload
  3. POST /admin/system/package/install
  4. GET /packages/{name}/index.php?cmd=id
Variants tested

Distinct alternate RCE sink: the same UserApiController::saveAction() privilege escalation (only blocks Administrator role id=3) grants the trusted 'system: software updates' permission instead of 'system: manage packages', unlocking a SECOND independent RCE sink — UpdateController::downloadAction + updateAction drive…

How the agent worked 707 events · 291 tool calls · 23 min
23 minDuration
291Tool calls
188Reasoning steps
707Events
2Dead-ends
Agent activity over 23 min
Support
20
Repro
477
Judge
18
Variant
188
0:0023:15

Root Cause and Exploit Chain for CVE-2026-57518

Versions: Pagekit CMS ≤ 1.0.18 (project archived 2023-12-01;

Pagekit CMS 1.0.18 contains a privilege escalation vulnerability in UserApiController::saveAction() that allows authenticated users holding the user: manage users permission to self-assign arbitrary custom roles. The authorization check only prevents assignment of the built-in Administrator role (hard-coded ID=3); any custom role (ID ≥ 4) — including one with elevated permissions such as system: manage packages — passes through unchecked. An attacker can exploit this to gain the system: manage packages permission, then upload and install a malicious PHP extension package containing a webshell through the admin package installer, achieving remote code execution on the server.

  • Package/component affected: pagekit/pagekitapp/system/modules/user/src/Controller/UserApiController.php (saveAction, lines 178–183)
  • Affected versions: Pagekit CMS ≤ 1.0.18 (project archived 2023-12-01; no patched release exists)
  • Risk level: High (CVSS 8.8 — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
  • Consequences: Full server compromise. An authenticated low-privileged user with user: manage users can escalate to arbitrary code execution as the web server user (www-data).

Impact Parity

  • Disclosed/claimed maximum impact: Privilege escalation leading to remote code execution (code_execution)
  • Reproduced impact from this run: Full privilege escalation to system: manage packages, followed by upload and installation of a malicious PHP package, followed by confirmed remote code execution (uid=33(www-data))
  • Parity: full
  • Not demonstrated: N/A — the full chain from low-privilege user to arbitrary command execution was demonstrated end-to-end against the real running Pagekit service via its HTTP API.

Root Cause

The vulnerability is in UserApiController::saveAction() at app/system/modules/user/src/Controller/UserApiController.php, lines 178–183:

$key    = array_search(Role::ROLE_ADMINISTRATOR, @$data['roles'] ?: []);
$add    = false !== $key && !$user->isAdministrator();
$remove = false === $key && $user->isAdministrator();

if (($self && $remove) || !App::user()->isAdministrator() && ($remove || $add)) {
    App::abort(403, 'Cannot add/remove Admin Role.');
}

Role::ROLE_ADMINISTRATOR is a constant equal to 3 (defined in app/system/modules/user/src/Model/Role.php). The authorization check only tests whether the Administrator role (ID=3) is being added or removed. Custom roles created by an administrator (which receive IDs 4, 5, 6, …) are never subjected to any authorization check. Consequently, any user who has the user: manage users permission (required by the @Access("user: manage users") annotation on UserApiController) can call POST /api/user/{own_id} with a roles array that includes a custom role with elevated permissions — for example, system: manage packages — and the server will silently accept and persist the change.

Once the attacker holds system: manage packages (and system: access admin area), the admin package installer at POST /admin/system/package/upload and POST /admin/system/package/install becomes available. The attacker uploads a ZIP archive containing a composer.json (type pagekit-extension) and a PHP webshell (index.php). The installer extracts the package into the web-accessible packages/ directory, and the webshell is immediately reachable at /packages/pagekit/shell/index.php?cmd=<command>, executing arbitrary commands as the web server user.

Fix commit: None — the Pagekit project was archived on 2023-12-01 and no patched version has been released.

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh
  2. What the script does:
    • Downloads (or reuses a cached copy of) the official Pagekit 1.0.18 release ZIP (which includes all PHP dependencies in app/vendor/).
    • Builds a Docker image based on php:7.4-apache with the required PHP extensions (gd, zip, pdo_sqlite, opcache) and deploys Pagekit with Apache + mod_rewrite.
    • Starts the container and installs Pagekit via its installer API (POST /installer/install) using a SQLite database, creating an administrator account.
    • As administrator, creates two custom roles:
      • Package Manager (ID 4): system: manage packages + system: access admin area
      • User Manager (ID 5): user: manage users
    • As administrator, creates a low-privileged editor user (ID 2) with the User Manager role.
    • As editor, calls POST /api/user/2 with {"user":{"id":2,"roles":[2,4]}} — self-assigning the Package Manager role. The saveAction only blocks role ID 3 (Administrator); the custom role ID 4 passes through unchecked.
    • As the now-escalated editor, uploads a malicious extension ZIP (containing a PHP webshell) via POST /admin/system/package/upload and installs it via POST /admin/system/package/install.
    • Accesses /packages/pagekit/shell/index.php?cmd=id and verifies the output contains uid=, confirming remote code execution.
  3. Expected evidence of reproduction:
    • bundle/logs/reproduction_steps.log — full execution log
    • bundle/logs/exploit_evidence.txt — structured evidence summary
    • bundle/logs/rce_id_output.txt — output of id command via webshell (uid=33(www-data) gid=33(www-data) groups=33(www-data))
    • bundle/logs/rce_whoami_output.txt — output of whoami (www-data)
    • bundle/repro/runtime_manifest.json — runtime evidence manifest

Evidence

Key excerpts

Privilege escalation (Step 3):

Editor BEFORE escalation: {"id":2,...,"roles":[2,5],...}
Escalation response: {"message":"success","user":{"id":2,...,"roles":[2,4],...}}
PRIVILEGE ESCALATION CONFIRMED — editor now has 'system: manage packages'

RCE (Step 6):

RCE output (id): uid=33(www-data) gid=33(www-data) groups=33(www-data)
RCE output (whoami): www-data
=== RCE CONFIRMED ===
Environment details
  • OS: Ubuntu 26.04 LTS (host); Debian Bullseye (container)
  • PHP: 7.4.33 (Apache, inside Docker container)
  • Database: SQLite (pagekit.db)
  • Pagekit: 1.0.18 (official release from GitHub)
  • Web server: Apache 2.4.54 with mod_rewrite
Sandbox adaptations (non-security-relevant)
  1. Docker networking: The sandbox restricts host-to-container port forwarding, so all HTTP requests to the running Pagekit service are made via docker exec (curl inside the container). This does not alter the product's request handling — the same HTTP requests reach the same Apache
    • PHP + Pagekit stack.
  2. Session bootstrap: A PHP helper (create_session.php) creates a valid authenticated session directly in the database (session + auth tables) to bypass a PHP 7.4 / Symfony 3.0 session-storage interaction issue that prevents normal web login via curl. The auth state created is identical to a successful web login (same cookies, same database records, same CSRF token derivation).
  3. Composer marketplace repository: The package installer's Composer blueprint includes a remote composer repository pointing to https://pagekit.com. The sandbox has no outbound network, so this repository entry is removed from the blueprint, leaving only the local artifact repository. This does not change any security-relevant code path — it only avoids a network fetch for the marketplace index that is irrelevant to the exploit.

Recommendations / Next Steps

Suggested fix

The authorization check in saveAction should validate all role assignments, not just the Administrator role. A correct implementation would verify that the calling user is permitted to assign each role in the $data['roles'] array — for example, by checking that the calling user either is an administrator or holds a permission that authorizes assigning each specific role. At minimum, the check should prevent any non-administrator from assigning roles with trusted permissions (such as system: manage packages) to themselves.

Upgrade guidance

Pagekit is archived and unmaintained. Users should migrate to an actively maintained CMS. If migration is not immediately feasible, a mitigation is to never grant the user: manage users permission to non-administrator accounts, and to avoid creating custom roles with trusted permissions.

Testing recommendations
  • Add a unit test that verifies a non-administrator user with user: manage users cannot self-assign a custom role with trusted permissions.
  • Add an integration test that verifies the package installer rejects uploads from users without system: manage packages.

Additional Notes

Idempotency confirmation

The script was run twice consecutively, both times producing the same result: privilege escalation confirmed and RCE confirmed (uid=33(www-data)). Each run creates a fresh Docker container with a clean Pagekit installation, ensuring no state carries over between runs.

Limitations
  • The project is archived; no fixed version exists for a negative control.
  • The webshell executes as www-data (the Apache user), not as root. Full root compromise would require a separate local privilege escalation, which is out of scope for this CVE.
  • The user: manage users precondition is realistic: Pagekit supports delegating user management to non-owner accounts (e.g., a "User Manager" or "Editor" role), which is the exact scenario this vulnerability targets.

Variant Analysis & Alternative Triggers for CVE-2026-57518

Versions: versions (as tested): Pagekit 1.0.18, commit

A distinct alternate RCE sink was found and confirmed at runtime. The parent CVE-2026-57518 demonstrates that an authenticated low-privileged user holding user: manage users can self-assign an arbitrary custom role via UserApiController::saveAction() (which only blocks the built-in Administrator role id=3) and then RCE through the package installer (POST /admin/system/package/upload|install, gated by system: manage packages). This variant shows that the same saveAction escalation grants a different trusted permission — system: software updates — which unlocks a second, independent RCE sink: UpdateController::downloadAction + updateAction (POST /admin/system/update/download + POST /admin/system/update/update). downloadAction fetches an attacker-controlled URL (a file:// URL copies a locally planted archive with no network needed) into a server-side temp file, and updateAction runs SelfUpdater::update(), which extracts the archive over the Pagekit root (App::path()). A webshell placed at the archive root is written to /var/www/html/<name>.php and executed directly by Apache. RCE as www-data was confirmed (uid=33(www-data)). This is an alternate trigger / sink, not a bypass of a fix — no patched version exists (project archived).

Fix Coverage / Assumptions

  • Invariant the (would-be) fix relies on: the saveAction check assumes that only the built-in Administrator role (id=3) is privileged, and that blocking add/remove of id=3 for non-administrators is sufficient to prevent privilege escalation.
  • Code path it explicitly covers: adding or removing Role::ROLE_ADMINISTRATOR (id=3) on any target user by a non-administrator caller.
  • What it does NOT cover: (a) assignment of any custom role (id ≥ 4), including roles carrying trusted permissions such as system: manage packages, system: software updates, user: manage user permissions, system: access system settings; (b) the trusted permission flag, which is advisory UI-only and never enforced server-side; (c) the second RCE sink (UpdateController / SelfUpdater) that becomes reachable once system: software updates is obtained — the parent reproduction only exercises the package-installer sink.

Variant / Alternate Trigger

Entry points (distinct from the parent):

  1. POST /api/user/{id}UserApiController::saveAction() (app/system/modules/user/src/Controller/UserApiController.php, lines ~178–183). Same escalation root cause as the parent, but the self-assigned custom role carries system: software updates + system: access admin area instead of system: manage packages.
  2. POST /admin/system/update/downloadUpdateController::downloadAction() (app/installer/src/Controller/UpdateController.php). Attacker-controlled url parameter; file_put_contents(tempnam(path.temp,'update_'), fopen($url,'r')). The server copies the crafted "update" ZIP into a temp file whose path is stored in the session as system.update.
  3. POST /admin/system/update/updateUpdateController::updateAction(). Reads system.update from the session and invokes SelfUpdater::update($file) (app/installer/src/SelfUpdater.php), which extracts the ZIP over App::path() (the Pagekit web root).
  4. GET /rce_variant.php?cmd=id — the extracted webshell, served directly by Apache (root .htaccess only rewrites non-existent paths: RewriteCond %{REQUEST_FILENAME} !-f).

Why this is materially distinct from the parent (not a relabel):

Dimension Parent (CVE-2026-57518) This variant
Admin endpoint /admin/system/package /admin/system/update
Required permission system: manage packages system: software updates
Payload format pagekit-extension ZIP with composer.json "self-update" ZIP with app/installer/requirements.php
Sink primitive PackageManager extracts into packages/ SelfUpdater::extract() overwrites core files at web root
Network need local upload (multipart) file:// URL → server-side copy (no outbound network)

The escalation root cause is shared (the saveAction id=3-only check), which is exactly why a complete fix must block self-assignment of all trusted/elevated permissions and treat both admin sinks as exposed.

  • Package/component affected: pagekit/pagekit
    • Escalation: app/system/modules/user/src/Controller/UserApiController.php (saveAction)
    • Variant sink: app/installer/src/Controller/UpdateController.php (downloadAction, updateAction) and app/installer/src/SelfUpdater.php (update, extract)
  • Affected versions (as tested): Pagekit 1.0.18, commit 95446c5f08fc43993fad5e2b581743ffcce50c35 (only tag / latest commit; project archived 2023-12-01; no patched version exists).
  • Risk level: High (CVSS 8.8 — same as parent: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H).
  • Consequences: Full server compromise as the web server user (www-data). The self-updater sink is arguably more powerful than the package-installer sink: it can overwrite any file under the Pagekit root (not just packages/), limited only by www-data write permissions and the packages//storage//`.htaccess ignore list.

Impact Parity

  • Disclosed/claimed maximum impact (parent): Privilege escalation leading to remote code execution (code_execution).
  • Reproduced impact from this variant run: Full privilege escalation to system: software updates, followed by UpdateController download + update driving SelfUpdater to extract an attacker webshell to the web root, followed by confirmed RCE (uid=33(www-data) gid=33(www-data) groups=33(www-data), whoami=www-data).
  • Parity: full.
  • Not demonstrated: Root access (RCE is as www-data, same as the parent). Persistence/defense-evasion beyond a single webshell was not attempted.

Root Cause

UserApiController::saveAction() authorizes role changes by searching the submitted roles array for only Role::ROLE_ADMINISTRATOR (constant 3):

$key    = array_search(Role::ROLE_ADMINISTRATOR, @$data['roles'] ?: []);
$add    = false !== $key && !$user->isAdministrator();
$remove = false === $key && $user->isAdministrator();
if (($self && $remove) || !App::user()->isAdministrator() && ($remove || $add)) {
    App::abort(403, 'Cannot add/remove Admin Role.');
}

Because $add/$remove are derived solely from the presence/absence of id=3, any custom role (id ≥ 4) produces $add = $remove = false, so the guard never fires for a non-administrator caller. The submitted roles are then persisted unchanged via $user->save($data). A custom role created by an administrator that carries system: software updates (a trusted permission that is advisory-only server-side) can therefore be self-assigned by any user with user: manage users. Once held, UpdateController — gated only by @Access("system: software updates", admin=true) — exposes an arbitrary-URL download and a SelfUpdater that extracts the downloaded archive over the web root, yielding RCE.

Fix commit: None. Pagekit 1.0.18 is the final release; the repository is archived.

Reproduction Steps

  1. Script: bundle/vuln_variant/reproduction_steps.sh
  2. What the script does:
    • Reuses the cached Pagekit 1.0.18 release and the pagekit-vuln-1018:repro Docker image (php:7.4-apache + SQLite), starts an isolated container pagekit-variant, and installs Pagekit via POST /installer/install.
    • As administrator, creates an Updater role (id=4) with system: software updates + system: access admin area, a User Manager role (id=5) with user: manage users, and a low-privileged editor user (id=2) holding only the User Manager role.
    • As editor, calls POST /api/user/2 with roles=[2,4] — self-assigning the Updater role. saveAction only blocks id=3, so id=4 passes through unchecked. Escalation confirmed (roles become [2,4]).
    • Crafts a malicious "self-update" ZIP (app/installer/requirements.php returning an empty getFailedRequirements() + a root-level webshell rce_variant.php) and plants it at /var/www/html/storage/evil_update.zip.
    • As the escalated editor, calls POST /admin/system/update/download with url=file:///var/www/html/storage/evil_update.zip (HTTP 200), then POST /admin/system/update/update (HTTP 200; SelfUpdater runs: "Extracting files...done", "Removing old files...done").
    • Accesses GET /rce_variant.php?cmd=id and verifies uid=33(www-data).
    • Performs the mandatory fixed-version check (none exists) and writes the runtime manifest + evidence.
  3. Expected evidence of reproduction:
    • bundle/logs/vuln_variant/reproduction_steps.log — full execution log
    • bundle/logs/vuln_variant/exploit_evidence.txt — structured evidence
    • bundle/logs/vuln_variant/rce_id_output.txtuid=33(www-data) gid=33(www-data) groups=33(www-data)
    • bundle/logs/vuln_variant/rce_whoami_output.txtwww-data
    • bundle/logs/vuln_variant/fixed_version.txt — no-fixed-version notice
    • bundle/vuln_variant/runtime_manifest.json — runtime evidence manifest

Evidence

Key excerpts

Privilege escalation (Step 3):

Editor BEFORE escalation: ...,"roles":[2,5],...
Escalation response: {"message":"success","user":{"id":2,...,"roles":[2,4],...}}
PRIVILEGE ESCALATION CONFIRMED — editor now has 'system: software updates'

Variant sink (Steps 5–6):

Download response: []  HTTP:200   (POST /admin/system/update/download, file:// URL)
Update response (tail): Removing old files...done.  Deactivating update mode...done.  HTTP:200
Webshell on disk (/var/www/html/rce_variant.php): yes

RCE (Step 7):

RCE output (id): uid=33(www-data) gid=33(www-data) groups=33(www-data)
RCE output (whoami): www-data
=== VARIANT RCE CONFIRMED ===
Environment details
  • OS: Ubuntu 26.04 LTS (host); Debian Bullseye (container)
  • PHP: 7.4.33 (Apache, inside Docker container)
  • Database: SQLite (pagekit.db)
  • Pagekit: 1.0.18 (official release; commit 95446c5f08fc43993fad5e2b581743ffcce50c35)
  • Web server: Apache 2.4.54 with mod_rewrite
Sandbox adaptations (non-security-relevant)
  1. Docker networking: all HTTP requests to the running service are made via docker exec (curl inside the container); this does not alter request handling.
  2. Session bootstrap: a PHP helper creates a valid authenticated session directly in the database (same approach as the parent repro, to bypass a PHP 7.4 / Symfony 3.0 session-storage interaction that prevents curl login). The resulting auth state is identical to a successful web login.
  3. file:// download URL: the variant uses file:// for downloadAction's $url so the server-side copy works without outbound network. This is strictly weaker than the real-world attack (where an attacker can host the archive on any HTTP server they control and pass an http:// URL); it does not change any security-relevant code path.

Recommendations / Next Steps

  1. Fix saveAction to validate every role, not just id=3. A non-administrator caller must be forbidden from assigning any role whose permissions are trusted/elevated, or (more conservatively) any role the caller does not already hold / any role granting a permission the caller lacks. Apply the same logic in bulkSaveAction (which delegates to saveAction).
  2. Enforce the trusted permission flag server-side. Today it is UI-only. The role-editor (RoleApiController) and the user-role assignment (UserApiController) should reject granting trusted permissions to roles that non-administrators can hold, and reject assigning such roles to non-administrator users.
  3. Harden UpdateController::downloadAction: validate/restrict the url scheme and host (no file://, no SSRF to internal hosts), and require signature/verification of update archives before SelfUpdater::extract() overwrites core files. Treat the self-updater as a sensitive RCE-equivalent sink equal to the package installer.
  4. Defense in depth: restrict SelfUpdater::extract() to a manifest of expected paths and refuse to write executable files outside an allow-list; do not blindly $zip->extractTo(App::path(), $fileList).

Additional Notes

Bypass vs. alternate trigger

This is an alternate trigger/sink, not a bypass of a released fix — no patched version exists (project archived 2023-12-01; 1.0.18 is the only tag and latest commit). The variant is confirmed on the only available (vulnerable) target and demonstrates that a complete remediation must cover both the package-installer and self-updater sinks and all trusted permissions.

Idempotency confirmation

bundle/vuln_variant/reproduction_steps.sh was executed three times consecutively. Every run produced the same result: privilege escalation to system: software updates confirmed, UpdateController download + update succeeded (HTTP 200), webshell written to the web root, and RCE confirmed (uid=33(www-data)). Each run starts a fresh container with a clean Pagekit installation, so no state carries over. Exit code 0 on every run.

Limitations
  • RCE executes as www-data (Apache user), not root — same as the parent.
  • The SelfUpdater cleanup step deletes app/ files absent from the update archive, which breaks the Pagekit application after extraction; the standalone root-level webshell (rce_variant.php) remains independently executable by Apache regardless, so RCE is still confirmed. A real attacker would include the full app/ tree in the archive to preserve a functional site.
  • The best-effort session-path probe (check_update_path.php) reported <not found> because Pagekit's exact session serialization layout for the system.update value differs from the naive regex; this is cosmetic only — the update step itself returned HTTP 200 with the SelfUpdater's "done" output and the webshell was verified on disk, which is the authoritative confirmation.

CVE-2026-57518 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:000:41
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-57518 · REPRO-20
0:01
0:03
web search
0:05
web search
0:08
0:09
0:11
web search
0:14
0:16
0:18
0:19
web search
0:27
0:27
extract_facts
no facts extracted
0:28
0:28
0:28
supportrepro
0:30
0:30
0:30
0:31
0:31
0:32
0:32
0:33
0:35
0:37
web search
0:38
web search
0:41
08 · How to Fix

How to Fix CVE-2026-57518

Upgrade pagekit/pagekit · github to None available; project archived or later.

Coming soon

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

10 · FAQ

FAQ: CVE-2026-57518

How does the CVE-2026-57518 escalation-to-RCE chain work?

A user holding user: manage users self-assigns a custom role (ID >= 4) that carries system: manage packages, then uses the resulting admin package-installer functionality to upload and install a malicious PHP extension package containing a web shell, achieving remote code execution as the web server user.

Which Pagekit versions are affected by CVE-2026-57518, and where is it fixed?

Pagekit CMS <= 1.0.18 is affected. The project is archived (as of 2023-12-01) and no patched release is available.

How severe is CVE-2026-57518?

High severity, CVSS 3.1 8.8, reflecting full server compromise achievable from an authenticated low-privileged account.

How can I reproduce CVE-2026-57518?

Download the verified script and run it in an isolated environment against Pagekit 1.0.18; it creates a low-privileged user with user: manage users, self-assigns a custom role granting system: manage packages, then uploads a malicious PHP package via the admin installer to confirm code execution as www-data.
11 · References

References for CVE-2026-57518

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