fix: Changed order of escape to prevent RCE#5498
Conversation
|
Docker Image for build 1 is available on DockerHub: Note Ensure you backup your NPM instance before testing this image! Especially if there are database changes. Warning Changes and additions to DNS Providers require verification by at least 2 members of the community! |
Code Review — Fix is Incomplete, Vulnerability Remains ExploitableThanks for the detailed write-up and for identifying this vulnerability. The PR correctly diagnoses the escaping-order bug, but the proposed fix does not fully close the RCE. Why the Fix Is Still VulnerableThe fundamental issue is that For the classic payload
Shell parsing:
The escaping-order fix only helps for inputs containing Correct FixesOption A — Use const escapedCredentials = certificate.meta.dns_provider_credentials
.replaceAll("\\", "\\\\")
.replaceAll("'", "'\\''"); // end-quote, escaped-quote, re-open-quoteFor input Option B — Avoid the shell entirely (strongly preferred): Replace the import fs from "node:fs/promises";
const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
if (typeof certificate.meta.dns_provider_credentials === "string") {
promises.push(
fs.mkdir("/etc/letsencrypt/credentials", { recursive: true })
.then(() => fs.writeFile(credentials_loc, certificate.meta.dns_provider_credentials, { mode: 0o600, flag: "wx" }))
);
}This removes the attack surface entirely rather than trying to sanitize around shell injection. Summary
Option B is the right long-term fix as it eliminates the entire class of shell-injection risk in this code path. |
Summary
Nginx Proxy Manager is vulnerable to authenticated remote code execution due to a shell injection in
setupCertbotPlugins()(backend/setup.js).The user-controlled field
dns_provider_credentialsis interpolated into a shell command executed viachild_process.exec()without proper escaping.An attacker with
certificates:managepermission can inject arbitrary commands, executed on backend restart (typically asrootin Docker deployments).Affected Versions
Root Cause
Incorrect escaping order:
Backslashes are escaped after single quotes, breaking the protection and allowing injection.
Example input:
Results in command execution:
Exploitation
dns_provider_credentials(DB or race condition)/bin/sh -cinsideexec()Reliable in Docker since
/etc/letsencrypt/credentials/is not persisted.Example payload:
Impact
Fix