{"claim_outcome": "confirmed", "claim_block_reason": null, "variant_result": "confirmed", "variant_kind": "alternate_trigger_and_sink", "bypass_of_fix": false, "no_fixed_version_available": true, "fixed_version_blocker": "Pagekit is archived (2023-12-01); 1.0.18 (commit 95446c5f08fc43993fad5e2b581743ffcce50c35) is the only git tag and the latest commit. No patched ref exists to test a bypass against; the variant is confirmed on the only available (vulnerable) target.", "validated_surface": "api_remote", "evidence_scope": "production_path", "claimed_impact_class": "code_execution", "observed_impact_class": "code_execution", "exploitability_confidence": "high", "attacker_controlled_input": "Authenticated low-privileged user with 'user: manage users' self-assigns a custom role carrying 'system: software updates' via POST /api/user/{id} (saveAction only blocks Administrator role id=3), then uses UpdateController::downloadAction (attacker-controlled url; file:// accepted) + updateAction (SelfUpdater extracts attacker ZIP over the Pagekit web root) to drop a webshell, then executes arbitrary commands via the webshell.", "trigger_path": "POST /api/user/{id} roles=[2,<updater_role_id>] -> saveAction (only blocks id=3) -> editor gains system: software updates -> POST /admin/system/update/download url=file:///...evil_update.zip -> POST /admin/system/update/update -> SelfUpdater::update extracts rce_variant.php to /var/www/html/ -> GET /rce_variant.php?cmd=id (uid=33(www-data))", "end_to_end_target_reached": true, "sanitizer_used": false, "crash_observed": false, "read_write_primitive_observed": true, "exploit_chain_demonstrated": true, "blocking_mitigation": null, "inferred": false, "distinct_from_parent": true, "distinct_dimensions": ["different admin endpoint (/admin/system/update vs /admin/system/package)", "different required permission (system: software updates vs system: manage packages)", "different payload format (self-update ZIP with app/installer/requirements.php vs pagekit-extension composer.json ZIP)", "different sink primitive (SelfUpdater::extract overwrites core files at web root vs PackageManager extract into packages/)", "no outbound network required (file:// download URL)"], "shared_root_cause": "UserApiController::saveAction() authorizes role changes by searching the submitted roles array only for Role::ROLE_ADMINISTRATOR (id=3); any custom role (id>=4) passes through unchecked, so any trusted permission (system: software updates, system: manage packages, etc.) can be self-assigned by a user with 'user: manage users'. The 'trusted' permission flag is advisory UI-only and is never enforced server-side.", "runtime_evidence": {"rce_id_output": "uid=33(www-data) gid=33(www-data) groups=33(www-data)", "rce_whoami_output": "www-data", "escalation_verified": "editor roles changed from [2,5] to [2,4] (Updater role with system: software updates)", "update_download_http": "200", "update_update_http": "200", "webshell_on_disk": "yes (/var/www/html/rce_variant.php)"}, "reproduction_script_exit_code": 0, "idempotency_runs": 3, "proof_artifacts": ["logs/vuln_variant/reproduction_steps.log", "logs/vuln_variant/exploit_evidence.txt", "logs/vuln_variant/rce_id_output.txt", "logs/vuln_variant/rce_whoami_output.txt", "logs/vuln_variant/fixed_version.txt"]}