From 9dd56441833c9de6e419cf74fff77820ae0f5f03 Mon Sep 17 00:00:00 2001
From: chaptergy <git@chaptergy.xyz>
Date: Wed, 29 Dec 2021 16:30:49 +0100
Subject: [PATCH] Correctly escape backslashes in dns plugin credentials

---
 backend/internal/certificate.js | 6 ++++--
 backend/setup.js                | 4 +++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 55f55d0..ece3a3c 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -870,8 +870,10 @@ const internalCertificate = {
 		logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
 
 		const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
-		const credentialsCmd      = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
-		const prepareCmd          = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
+		// Escape single quotes and backslashes
+		const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
+		const credentialsCmd     = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
+		const prepareCmd         = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
 
 		// Whether the plugin has a --<name>-credentials argument
 		const hasConfigArg = certificate.meta.dns_provider !== 'route53';
diff --git a/backend/setup.js b/backend/setup.js
index 41436c8..47fd1e7 100644
--- a/backend/setup.js
+++ b/backend/setup.js
@@ -181,7 +181,9 @@ const setupCertbotPlugins = () => {
 
 						// Make sure credentials file exists
 						const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id; 
-						const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
+						// Escape single quotes and backslashes
+						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));
 					}
 				});