CVE-2026-72573: Verified Reproduction
CVE-2026-72573: Authenticated command injection in pm2panel's /restart handler allows remote shell command execution on the host.
CVE-2026-72573 is verified against 4xmen/pm2panel · GitHub / Node.js web application. Affected versions: All versions (version 0 affected per CVE record, defaultStatus unknown). Fixed in None identified - no fix available. Vulnerability class: Command Injection. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00334.
What Is CVE-2026-72573?
CVE-2026-72573 is a high-severity Command Injection vulnerability affecting 4xmen/pm2panel All versions (version 0 affected per CVE record, defaultStatus unknown). Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00334).
CVE-2026-72573 Severity
CVE-2026-72573 is rated high severity.
High — serious impact or readily exploitable. Prioritize remediation.
Affected 4xmen/pm2panel Versions
4xmen/pm2panel · GitHub / Node.js web application versions All versions (version 0 affected per CVE record, defaultStatus unknown) are affected.
How to Reproduce CVE-2026-72573
pruva-verify REPRO-2026-00334 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00334/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-72573
- 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
req.query.id in authenticated HTTP GET /restart endpoint
- POST /loginCheck (auth)
- GET /restart?id=0;touch /tmp/pm2panel_pwned (command injection via child_process.exec)
How the agent worked
Root Cause and Exploit Chain for CVE-2026-72573
The 4xmen/pm2panel web application contains an OS command injection vulnerability in the authenticated /restart HTTP endpoint. The handler at line 188 of pm2panel.js concatenates the attacker-controlled req.query.id query parameter directly into a child_process.exec() shell command (exec("pm2 restart " + req.query.id)). Because exec invokes /bin/sh, shell metacharacters such as ;, &&, |, backticks, or $() in the id parameter are interpreted by the shell, allowing an authenticated attacker to execute arbitrary commands on the host with the privileges of the pm2panel process.
- Package/component affected:
4xmen/pm2panel(Node.js web application,pm2panel.js) - Affected versions: All versions (commit
dd2a7d2e8cb4dacefb618ab54b0a8f7dc6742fa0, latest onmaster) - Risk level: High — authenticated remote code execution
- Consequences: An attacker with valid panel credentials (default:
admin/admin) can execute arbitrary shell commands on the host server, leading to full system compromise, data exfiltration, lateral movement, or service disruption.
Impact Parity
- Disclosed/claimed maximum impact: Code execution (CWE-78, OS command injection)
- Reproduced impact from this run: Full arbitrary command execution — a marker file was created on the host filesystem via an injected
touchcommand through the authenticated/restartendpoint - Parity:
full - Not demonstrated: N/A — the full claimed impact was demonstrated
Root Cause
The /restart route handler in pm2panel.js (line 188) constructs a shell command by directly string-concatenating the user-supplied req.query.id query parameter:
app.get('/restart', function (req, res) {
if (!req.session.islogin) {
// redirect to login...
} else {
if (req.query.id) {
exec("pm2 restart " + req.query.id, (error, stdout, stderr) => {
// ...
});
}
}
});
child_process.exec() spawns a shell (/bin/sh -c) to run the command. The req.query.id value is never validated, sanitized, or shell-escaped. When an attacker sends a request like GET /restart?id=0; touch /tmp/pm2panel_pwned, the shell interprets the ; as a command separator and executes touch /tmp/pm2panel_pwned in addition to pm2 restart 0.
The same vulnerable pattern exists in four other handlers:
/start(line 218):exec("pm2 start " + req.query.id)/stop(line 248):exec("pm2 stop " + req.query.id)/delete(line 278):exec("pm2 delete " + req.query.id)/addProccess(line 149):exec('pm2 start "' + req.body.path + '"')
No fix commit has been identified; the vulnerability is present in the latest commit on master.
Reproduction Steps
- Reference script:
bundle/repro/reproduction_steps.sh - What the script does:
- Clones/reuses the
4xmen/pm2panelrepository from the project cache - Installs system dependencies (
libpam0g-dev) and npm dependencies (including nativenode-linux-pammodule) - Installs and starts PM2 with a demo process (id 0)
- Starts the pm2panel Express web application on port 3001
- Authenticates via
POST /loginCheckwith default credentials (admin/admin) - Sends an authenticated
GET /restart?id=0; touch /tmp/pm2panel_pwned_<pid>request - Verifies the marker file was created (proving arbitrary command execution)
- Runs negative controls: unauthenticated request is rejected (302 redirect), safe request without injection does not create a marker
- Clones/reuses the
- Expected evidence of reproduction:
- Marker file exists at
/tmp/pm2panel_pwned_*after the exploit request - HTTP 302 response from the exploit endpoint (normal redirect behavior)
- Unauthenticated requests return 302 redirect to
/login - Safe restart requests (no injection) do not create marker files
- Marker file exists at
Evidence
Log files:
bundle/logs/reproduction_steps.log— full script execution logbundle/logs/pm2panel_service.log— pm2panel application server logbundle/logs/artifacts/http/response_login.txt— login response with session cookiebundle/logs/artifacts/http/request_exploit.txt— exploit request detailsbundle/logs/artifacts/http/response_exploit.txt— exploit HTTP response (302)bundle/logs/artifacts/http/marker_evidence.txt— marker file existence and stat outputbundle/logs/artifacts/http/response_unauth.txt— unauthenticated request response (302 redirect)bundle/logs/artifacts/http/safe_restart_status.txt— safe restart response codebundle/repro/runtime_manifest.json— structured runtime evidence manifest
Key excerpts:
- Exploit request:
GET /restart?id=0;%20touch%20/tmp/pm2panel_pwned_3850 HTTP/1.1 - Exploit response:
HTTP/1.1 302 FoundwithLocation: / - Marker evidence:
MARKER_FILE_EXISTS=truewithstatoutput showing file creation timestamp - Negative control (unauthenticated):
302redirect to/login - Negative control (safe): no marker file created
- Exploit request:
Environment:
- Node.js v24.18.0, npm 11.16.0
- PM2 v7.0.3
- pm2panel commit
dd2a7d2e8cb4dacefb618ab54b0a8f7dc6742fa0 - Linux x86_64, Express 4.x, express-session
Recommendations / Next Steps
- Fix: Replace
child_process.execwithchild_process.execFile(which does not invoke a shell) and passreq.query.idas a separate argument array, or validatereq.query.idagainst a strict numeric regex before use. - Defense in depth: Implement input validation on all endpoints that accept process IDs (
/start,/stop,/delete,/addProccess). - Authentication: Change default credentials from
admin/adminand enforce strong password policies. - Upgrade guidance: No patched version exists. Users should apply the fix manually or discontinue use of the panel.
- Testing: Add integration tests that send shell metacharacters in query parameters and assert they are not interpreted by the shell.
Additional Notes
- Idempotency: The script uses process-specific marker file names (with
$$PID suffix) and cleans up PM2 processes and the pm2panel server on each run. It was verified to pass on two consecutive executions. - Authentication requirement: The vulnerability requires authentication. The script performs a proper login flow with
POST /loginCheckand session cookie extraction before sending the exploit request. - Multiple vulnerable endpoints: The same command injection pattern affects
/start,/stop,/delete, and/addProccessin addition to/restart. The reproduction focuses on/restartas specified in the claim.
CVE-2026-72573 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.
Unknown error
Unknown error
Artifacts and Evidence for CVE-2026-72573
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-72573
Upgrade 4xmen/pm2panel · GitHub / Node.js web application to None identified - no fix available or later.
FAQ: CVE-2026-72573
Is CVE-2026-72573 exploitable?
How severe is CVE-2026-72573?
What type of vulnerability is CVE-2026-72573?
Which versions of 4xmen/pm2panel are affected by CVE-2026-72573?
Is there a fix for CVE-2026-72573?
How can I reproduce CVE-2026-72573?
Is the CVE-2026-72573 reproduction verified?
References for CVE-2026-72573
Authoritative sources for CVE-2026-72573 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.