VYPR
High severity7.5NVD Advisory· Published Jun 8, 2026

CVE-2026-40519

CVE-2026-40519

Description

Nginx Proxy Manager 2.9.14-2.15.1 allows authenticated RCE by injecting OS commands into the dns_provider_credentials field.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Nginx Proxy Manager 2.9.14-2.15.1 allows authenticated RCE by injecting OS commands into the dns_provider_credentials field.

Vulnerability

Nginx Proxy Manager versions 2.9.14 through 2.15.1 contain an OS command injection vulnerability within the setupCertbotPlugins() function in backend/setup.js. This vulnerability is triggered when a user with certificates:manage permission stores a malicious payload in the dns_provider_credentials field, which is then directly interpolated into a shell command executed via child_process.exec() without proper sanitization or escaping [3]. The vulnerability was fixed in commit a5db5ed [2].

Exploitation

An attacker must first possess authenticated access to Nginx Proxy Manager and have the certificates:manage permission. The attacker can then craft a payload containing OS commands and store it within the dns_provider_credentials field. These commands will be executed when the backend restarts, as part of the setupCertbotPlugins() function's execution flow [3].

Impact

Successful exploitation of this vulnerability allows an attacker to execute arbitrary operating system commands with the privileges of the Nginx Proxy Manager process. This can lead to a full compromise of the server hosting Nginx Proxy Manager, including potential data theft, system modification, or further network intrusion [3].

Mitigation

Nginx Proxy Manager versions 2.9.14 through 2.15.1 are affected. The vulnerability was fixed in commit a5db5ed [2], which is included in version 2.15.2. Users are advised to update to version 2.15.2 or later as soon as possible. No workarounds are available for unpatched versions.

AI Insight generated on Jun 8, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
a5db5ed15635

Merge pull request #5498 from Yasha-ops/develop

1 file changed · +5 7
  • backend/setup.js+5 7 modified
    @@ -6,6 +6,7 @@ import certificateModel from "./models/certificate.js";
     import settingModel from "./models/setting.js";
     import userModel from "./models/user.js";
     import userPermissionModel from "./models/user_permission.js";
    +import fs from "fs/promises";
     
     export const isSetup = async () => {
     	const row = await userModel.query().select("id").where("is_deleted", 0).first();
    @@ -120,18 +121,15 @@ const setupCertbotPlugins = async () => {
     
     				// Make sure credentials file exists
     				const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
    -				// Escape single quotes and backslashes
     				if (typeof certificate.meta.dns_provider_credentials === "string") {
    -					const escapedCredentials = certificate.meta.dns_provider_credentials
    -						.replaceAll("'", "\\'")
    -						.replaceAll("\\", "\\\\");
    -					const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`;
    -					promises.push(utils.exec(credentials_cmd));
    +					promises.push(fs.mkdir("/etc/letsencrypt/credentials", { recursive: true })
    +								  .then(() => fs.writeFile(credentials_loc, certificate.meta.dns_provider_credentials, { mode: 0o600, flag: "wx" }))
    +								  .catch((err) => { if (err.code !== "EEXIST") throw err; }));
     				}
     			}
     			return true;
     		});
    -
    +		
     		await installPlugins(plugins);
     
     		if (promises.length) {
    

Vulnerability mechanics

Root cause

"OS command injection via unsanitized user input in the dns_provider_credentials field."

Attack vector

An attacker with certificates:manage permission can exploit this vulnerability. The attacker crafts a malicious payload within the dns_provider_credentials field when configuring certificate DNS provider credentials. This payload is then directly interpolated into a shell command executed by the setupCertbotPlugins() function. The command injection occurs because the user-controlled input is not properly sanitized or escaped before being passed to child_process.exec().

Affected code

The vulnerability resides in the setupCertbotPlugins() function within the backend/setup.js file. The original code constructed a shell command that included the `certificate.meta.dns_provider_credentials` value directly, which was susceptible to injection. The patch modifies this section to use `fs.mkdir` and `fs.writeFile` for handling the credentials file [ref_id=1].

What the fix does

The patch modifies the setupCertbotPlugins() function to use Node.js's `fs` module for file operations instead of constructing shell commands. Specifically, it replaces the direct execution of a shell command that wrote credentials to a file with `fs.mkdir` and `fs.writeFile`. This change ensures that the `dns_provider_credentials` are written to the file system directly, preventing the interpolation of malicious shell commands and thus closing the OS command injection vulnerability [patch_id=5247383].

Preconditions

  • authThe attacker must have an authenticated session with the 'certificates:manage' permission.
  • inputThe attacker must be able to control the value of the 'dns_provider_credentials' field.

Generated on Jun 8, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.