From 9df94a233d47615aca14b12ba29ea33f990dafa7 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <kmalhar@amazon.com>
Date: Fri, 27 Aug 2021 14:38:34 -0400
Subject: [PATCH 1/5] fix: Fixed an error caught by static code analysis

---
 src/AWS.Deploy.CLI/Commands/DeployCommand.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/AWS.Deploy.CLI/Commands/DeployCommand.cs b/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
index 1ba74afc2..51661d56d 100644
--- a/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
+++ b/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
@@ -43,7 +43,7 @@ public class DeployCommand
         private readonly ISystemCapabilityEvaluator _systemCapabilityEvaluator;
         private readonly OrchestratorSession _session;
         private readonly IDirectoryManager _directoryManager;
-        private ICDKVersionDetector _cdkVersionDetector;
+        private readonly ICDKVersionDetector _cdkVersionDetector;
 
         public DeployCommand(
             IToolInteractiveService toolInteractiveService,

From d85807eafad4dfc4973643b93a1482f256fed6ee Mon Sep 17 00:00:00 2001
From: aws-sdk-dotnet-automation <github-aws-sdk-dotnet-automation@amazon.com>
Date: Thu, 26 Aug 2021 14:29:40 +0000
Subject: [PATCH 2/5] build: version bump to 0.18

---
 version.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/version.json b/version.json
index 0cefc4d15..a4cc51e4d 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
 {
   "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
-  "version": "0.17",
+  "version": "0.18",
   "publicReleaseRefSpec": [
     ".*"
   ],

From 9a601078c74ba8d57501ead89d22d47bde3f4898 Mon Sep 17 00:00:00 2001
From: Philippe El Asmar <phil.asmar@gmail.com>
Date: Thu, 26 Aug 2021 13:34:19 -0400
Subject: [PATCH 3/5] fix: reusing AES IV could cause potential security risks

---
 .../Commands/ServerModeCommand.cs             |  4 ---
 .../AwsCredentialsAuthenticationHandler.cs    | 28 ++++++++++++++++---
 .../Services/AesEncryptionProvider.cs         |  6 ++--
 .../Services/IEncryptionProvider.cs           |  2 +-
 .../Services/NoEncryptionProvider.cs          |  2 +-
 .../ServerModeHttpClient.cs                   |  3 +-
 .../ServerModeSession.cs                      |  8 ++----
 7 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs
index d14b4aa41..58644331f 100644
--- a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs
+++ b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs
@@ -104,10 +104,6 @@ private IEncryptionProvider CreateEncryptionProvider()
                         {
                             aes.Key = Convert.FromBase64String(keyInfo.Key);
                         }
-                        if (keyInfo.IV != null)
-                        {
-                            aes.IV = Convert.FromBase64String(keyInfo.IV);
-                        }
 
                         encryptionProvider = new AesEncryptionProvider(aes);
                         break;
diff --git a/src/AWS.Deploy.CLI/ServerMode/AwsCredentialsAuthenticationHandler.cs b/src/AWS.Deploy.CLI/ServerMode/AwsCredentialsAuthenticationHandler.cs
index 42703bbd3..ba83907bb 100644
--- a/src/AWS.Deploy.CLI/ServerMode/AwsCredentialsAuthenticationHandler.cs
+++ b/src/AWS.Deploy.CLI/ServerMode/AwsCredentialsAuthenticationHandler.cs
@@ -82,9 +82,18 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
         public static AuthenticateResult ProcessAuthorizationHeader(string authorizationHeaderValue, IEncryptionProvider encryptionProvider)
         {
             var tokens = authorizationHeaderValue.Split(' ');
-            if (tokens.Length != 2)
+            if (tokens.Length != 2 && tokens.Length != 3)
             {
-                return AuthenticateResult.Fail($"Incorrect format Authorization header. Format should be \"{SchemaName} <base-64-auth-parameters>\"");
+                var ivPlaceholder = "";
+                if (encryptionProvider is AesEncryptionProvider)
+                {
+                    ivPlaceholder = "<iv> ";
+                }
+                return AuthenticateResult.Fail($"Incorrect format Authorization header. Format should be \"{SchemaName} {ivPlaceholder}<base-64-auth-parameters>\"");
+            }
+            if (tokens.Length == 2 && encryptionProvider is AesEncryptionProvider)
+            {
+                return AuthenticateResult.Fail($"Incorrect format Authorization header. Format should be \"{SchemaName} <iv> <base-64-auth-parameters>\"");
             }
             if (!string.Equals(SchemaName, tokens[0]))
             {
@@ -93,9 +102,20 @@ public static AuthenticateResult ProcessAuthorizationHeader(string authorization
 
             try
             {
-                var base64Bytes = Convert.FromBase64String(tokens[1]);
+                byte[]? base64IV;
+                byte[] base64Bytes;
+                if (tokens.Length == 2)
+                {
+                    base64IV = null;
+                    base64Bytes = Convert.FromBase64String(tokens[1]);
+                }
+                else
+                {
+                    base64IV = Convert.FromBase64String(tokens[1]);
+                    base64Bytes = Convert.FromBase64String(tokens[2]);
+                }
 
-                var decryptedBytes = encryptionProvider.Decrypt(base64Bytes);
+                var decryptedBytes = encryptionProvider.Decrypt(base64Bytes, base64IV);
                 var json = Encoding.UTF8.GetString(decryptedBytes);
 
                 var authParameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
diff --git a/src/AWS.Deploy.CLI/ServerMode/Services/AesEncryptionProvider.cs b/src/AWS.Deploy.CLI/ServerMode/Services/AesEncryptionProvider.cs
index 2fa02f367..e5e13a44b 100644
--- a/src/AWS.Deploy.CLI/ServerMode/Services/AesEncryptionProvider.cs
+++ b/src/AWS.Deploy.CLI/ServerMode/Services/AesEncryptionProvider.cs
@@ -19,9 +19,9 @@ public AesEncryptionProvider(Aes aes)
             _aes = aes;
         }
 
-        public byte[] Decrypt(byte[] encryptedData)
-        {            
-            var decryptor = _aes.CreateDecryptor(_aes.Key, _aes.IV);
+        public byte[] Decrypt(byte[] encryptedData, byte[]? generatedIV)
+        {
+            var decryptor = _aes.CreateDecryptor(_aes.Key, generatedIV);
 
             using var inputStream = new MemoryStream(encryptedData);
             using var decryptStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read);
diff --git a/src/AWS.Deploy.CLI/ServerMode/Services/IEncryptionProvider.cs b/src/AWS.Deploy.CLI/ServerMode/Services/IEncryptionProvider.cs
index d32fc9de7..ca61a92d9 100644
--- a/src/AWS.Deploy.CLI/ServerMode/Services/IEncryptionProvider.cs
+++ b/src/AWS.Deploy.CLI/ServerMode/Services/IEncryptionProvider.cs
@@ -10,6 +10,6 @@ namespace AWS.Deploy.CLI.ServerMode.Services
 {
     public interface IEncryptionProvider
     {
-        byte[] Decrypt(byte[] encryptedData);
+        byte[] Decrypt(byte[] encryptedData, byte[]? generatedIV);
     }
 }
diff --git a/src/AWS.Deploy.CLI/ServerMode/Services/NoEncryptionProvider.cs b/src/AWS.Deploy.CLI/ServerMode/Services/NoEncryptionProvider.cs
index 0feab1b26..4a14977d4 100644
--- a/src/AWS.Deploy.CLI/ServerMode/Services/NoEncryptionProvider.cs
+++ b/src/AWS.Deploy.CLI/ServerMode/Services/NoEncryptionProvider.cs
@@ -10,6 +10,6 @@ namespace AWS.Deploy.CLI.ServerMode.Services
 {
     public class NoEncryptionProvider : IEncryptionProvider
     {
-        public byte[] Decrypt(byte[] encryptedData) => encryptedData;
+        public byte[] Decrypt(byte[] encryptedData, byte[]? generatedIV) => encryptedData;
     }
 }
diff --git a/src/AWS.Deploy.ServerMode.Client/ServerModeHttpClient.cs b/src/AWS.Deploy.ServerMode.Client/ServerModeHttpClient.cs
index 0f9767c9a..c86fc10f8 100644
--- a/src/AWS.Deploy.ServerMode.Client/ServerModeHttpClient.cs
+++ b/src/AWS.Deploy.ServerMode.Client/ServerModeHttpClient.cs
@@ -73,6 +73,7 @@ public static void AddAuthorizationHeader(HttpRequestMessage request, ImmutableC
             string base64;
             if(aes != null)
             {
+                aes.GenerateIV();
                 var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
 
                 using var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(json));
@@ -82,7 +83,7 @@ public static void AddAuthorizationHeader(HttpRequestMessage request, ImmutableC
                     inputStream.CopyTo(encryptStream);
                 }
 
-                base64 = Convert.ToBase64String(outputStream.ToArray());
+                base64 = $"{Convert.ToBase64String(aes.IV)} {Convert.ToBase64String(outputStream.ToArray())}";
             }
             else
             {
diff --git a/src/AWS.Deploy.ServerMode.Client/ServerModeSession.cs b/src/AWS.Deploy.ServerMode.Client/ServerModeSession.cs
index a33859fe0..e9ce6c337 100644
--- a/src/AWS.Deploy.ServerMode.Client/ServerModeSession.cs
+++ b/src/AWS.Deploy.ServerMode.Client/ServerModeSession.cs
@@ -128,12 +128,10 @@ public async Task Start(CancellationToken cancellationToken)
             {
                 _aes = Aes.Create();
                 _aes.GenerateKey();
-                _aes.GenerateIV();
 
                 var keyInfo = new EncryptionKeyInfo(
                     EncryptionKeyInfo.VERSION_1_0,
-                    Convert.ToBase64String(_aes.Key),
-                    Convert.ToBase64String(_aes.IV));
+                    Convert.ToBase64String(_aes.Key));
 
                 var keyInfoStdin = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(keyInfo)));
 
@@ -245,9 +243,9 @@ private class EncryptionKeyInfo
 
             public string Version { get; set; }
             public string Key { get; set; }
-            public string IV { get; set; }
+            public string? IV { get; set; }
 
-            public EncryptionKeyInfo(string version, string key, string iv)
+            public EncryptionKeyInfo(string version, string key, string? iv = null)
             {
                 Version = version;
                 Key = key;

From 5b9252ffd968abbfeb588efc804f1d7135f23cd5 Mon Sep 17 00:00:00 2001
From: Philippe El Asmar <phil.asmar@gmail.com>
Date: Fri, 27 Aug 2021 11:09:27 -0400
Subject: [PATCH 4/5] fix: disallow SMB shares from file paths

---
 src/AWS.Deploy.CLI/AWSUtilities.cs            |  7 +++-
 src/AWS.Deploy.CLI/Commands/CommandFactory.cs |  2 +-
 src/AWS.Deploy.CLI/Commands/DeployCommand.cs  |  4 +-
 .../DockerExecutionDirectoryCommand.cs        |  7 +++-
 .../TypeHints/TypeHintCommandFactory.cs       |  5 ++-
 src/AWS.Deploy.CLI/ConsoleUtilities.cs        |  7 +++-
 .../Controllers/DeploymentController.cs       |  4 +-
 .../AssumeRoleMfaTokenCodeCallback.cs         |  7 +++-
 src/AWS.Deploy.Common/IO/DirectoryManager.cs  | 14 ++++++-
 src/AWS.Deploy.Common/IO/FileManager.cs       | 15 ++++++-
 .../Utilities/PathUtilities.cs                | 30 ++++++++++++++
 src/AWS.Deploy.DockerEngine/DockerEngine.cs   |  7 +++-
 src/AWS.Deploy.Orchestration/Orchestrator.cs  |  4 +-
 .../Utilities/ZipFileManager.cs               | 11 ++++--
 .../ConsoleUtilitiesTests.cs                  | 39 ++++++++++++-------
 test/AWS.Deploy.CLI.UnitTests/DockerTests.cs  |  6 ++-
 .../RecommendationTests.cs                    | 12 +++++-
 17 files changed, 139 insertions(+), 42 deletions(-)
 create mode 100644 src/AWS.Deploy.Common/Utilities/PathUtilities.cs

diff --git a/src/AWS.Deploy.CLI/AWSUtilities.cs b/src/AWS.Deploy.CLI/AWSUtilities.cs
index 5d0621e5a..66b5c382b 100644
--- a/src/AWS.Deploy.CLI/AWSUtilities.cs
+++ b/src/AWS.Deploy.CLI/AWSUtilities.cs
@@ -9,6 +9,7 @@
 using Amazon.EC2.Model;
 using System.IO;
 using AWS.Deploy.CLI.Utilities;
+using AWS.Deploy.Common.IO;
 
 namespace AWS.Deploy.CLI
 {
@@ -22,11 +23,13 @@ public class AWSUtilities : IAWSUtilities
     {
         private readonly IToolInteractiveService _toolInteractiveService;
         private readonly IConsoleUtilities _consoleUtilities;
+        private readonly IDirectoryManager _directoryManager;
 
-        public AWSUtilities(IToolInteractiveService toolInteractiveService, IConsoleUtilities consoleUtilities)
+        public AWSUtilities(IToolInteractiveService toolInteractiveService, IConsoleUtilities consoleUtilities, IDirectoryManager directoryManager)
         {
             _toolInteractiveService = toolInteractiveService;
             _consoleUtilities = consoleUtilities;
+            _directoryManager = directoryManager;
         }
 
         public async Task<AWSCredentials> ResolveAWSCredentials(string? profileName, string? lastUsedProfileName = null)
@@ -89,7 +92,7 @@ await CanLoadCredentials(lastUsedCredentials))
             if (credentials is AssumeRoleAWSCredentials assumeRoleAWSCredentials)
             {
                 var assumeOptions = assumeRoleAWSCredentials.Options;
-                assumeOptions.MfaTokenCodeCallback = new AssumeRoleMfaTokenCodeCallback(_toolInteractiveService, assumeOptions).Execute;
+                assumeOptions.MfaTokenCodeCallback = new AssumeRoleMfaTokenCodeCallback(_toolInteractiveService, _directoryManager, assumeOptions).Execute;
             }
 
             return credentials;
diff --git a/src/AWS.Deploy.CLI/Commands/CommandFactory.cs b/src/AWS.Deploy.CLI/Commands/CommandFactory.cs
index 16d043681..60d11511a 100644
--- a/src/AWS.Deploy.CLI/Commands/CommandFactory.cs
+++ b/src/AWS.Deploy.CLI/Commands/CommandFactory.cs
@@ -190,7 +190,7 @@ private Command BuildDeployCommand()
                         AWSProfileName = input.Profile ?? userDeploymentSettings?.AWSProfile ?? null
                     };
 
-                    var dockerEngine = new DockerEngine.DockerEngine(projectDefinition);
+                    var dockerEngine = new DockerEngine.DockerEngine(projectDefinition, _fileManager);
 
                     var deploy = new DeployCommand(
                         _toolInteractiveService,
diff --git a/src/AWS.Deploy.CLI/Commands/DeployCommand.cs b/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
index 51661d56d..1e9184a15 100644
--- a/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
+++ b/src/AWS.Deploy.CLI/Commands/DeployCommand.cs
@@ -390,7 +390,7 @@ private void SetDeploymentBundleOptionSetting(Recommendation recommendation, str
             switch (optionSettingId)
             {
                 case "DockerExecutionDirectory":
-                    new DockerExecutionDirectoryCommand(_consoleUtilities).OverrideValue(recommendation, settingValue.ToString() ?? "");
+                    new DockerExecutionDirectoryCommand(_consoleUtilities, _directoryManager).OverrideValue(recommendation, settingValue.ToString() ?? "");
                     break;
                 case "DockerBuildArgs":
                     new DockerBuildArgsCommand(_consoleUtilities).OverrideValue(recommendation, settingValue.ToString() ?? "");
@@ -571,7 +571,7 @@ private async Task CreateDeploymentBundle(Orchestrator orchestrator, Recommendat
                             selectedRecommendation.DeploymentBundle.DockerExecutionDirectory,
                             allowEmpty: true);
 
-                        if (!Directory.Exists(dockerExecutionDirectory))
+                        if (!_directoryManager.Exists(dockerExecutionDirectory))
                             continue;
 
                         selectedRecommendation.DeploymentBundle.DockerExecutionDirectory = dockerExecutionDirectory;
diff --git a/src/AWS.Deploy.CLI/Commands/TypeHints/DockerExecutionDirectoryCommand.cs b/src/AWS.Deploy.CLI/Commands/TypeHints/DockerExecutionDirectoryCommand.cs
index 68e5f1014..38718620c 100644
--- a/src/AWS.Deploy.CLI/Commands/TypeHints/DockerExecutionDirectoryCommand.cs
+++ b/src/AWS.Deploy.CLI/Commands/TypeHints/DockerExecutionDirectoryCommand.cs
@@ -4,6 +4,7 @@
 using System.IO;
 using System.Threading.Tasks;
 using AWS.Deploy.Common;
+using AWS.Deploy.Common.IO;
 using AWS.Deploy.Common.Recipes;
 
 namespace AWS.Deploy.CLI.Commands.TypeHints
@@ -11,10 +12,12 @@ namespace AWS.Deploy.CLI.Commands.TypeHints
     public class DockerExecutionDirectoryCommand : ITypeHintCommand
     {
         private readonly IConsoleUtilities _consoleUtilities;
+        private readonly IDirectoryManager _directoryManager;
 
-        public DockerExecutionDirectoryCommand(IConsoleUtilities consoleUtilities)
+        public DockerExecutionDirectoryCommand(IConsoleUtilities consoleUtilities, IDirectoryManager directoryManager)
         {
             _consoleUtilities = consoleUtilities;
+            _directoryManager = directoryManager;
         }
 
         public Task<object> Execute(Recommendation recommendation, OptionSettingItem optionSetting)
@@ -47,7 +50,7 @@ public void OverrideValue(Recommendation recommendation, string executionDirecto
 
         private string ValidateExecutionDirectory(string executionDirectory)
         {
-            if (!string.IsNullOrEmpty(executionDirectory) && !Directory.Exists(executionDirectory))
+            if (!string.IsNullOrEmpty(executionDirectory) && !_directoryManager.Exists(executionDirectory))
                 return "The directory specified for Docker execution does not exist.";
             else
                 return "";
diff --git a/src/AWS.Deploy.CLI/Commands/TypeHints/TypeHintCommandFactory.cs b/src/AWS.Deploy.CLI/Commands/TypeHints/TypeHintCommandFactory.cs
index 3775c664e..8999dd1f4 100644
--- a/src/AWS.Deploy.CLI/Commands/TypeHints/TypeHintCommandFactory.cs
+++ b/src/AWS.Deploy.CLI/Commands/TypeHints/TypeHintCommandFactory.cs
@@ -4,6 +4,7 @@
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using AWS.Deploy.Common;
+using AWS.Deploy.Common.IO;
 using AWS.Deploy.Common.Recipes;
 using AWS.Deploy.Orchestration.Data;
 
@@ -29,7 +30,7 @@ public class TypeHintCommandFactory : ITypeHintCommandFactory
     {
         private readonly Dictionary<OptionSettingTypeHint, ITypeHintCommand> _commands;
 
-        public TypeHintCommandFactory(IToolInteractiveService toolInteractiveService, IAWSResourceQueryer awsResourceQueryer, IConsoleUtilities consoleUtilities)
+        public TypeHintCommandFactory(IToolInteractiveService toolInteractiveService, IAWSResourceQueryer awsResourceQueryer, IConsoleUtilities consoleUtilities, IDirectoryManager directoryManager)
         {
             _commands = new Dictionary<OptionSettingTypeHint, ITypeHintCommand>
             {
@@ -42,7 +43,7 @@ public TypeHintCommandFactory(IToolInteractiveService toolInteractiveService, IA
                 { OptionSettingTypeHint.DotnetPublishAdditionalBuildArguments, new DotnetPublishArgsCommand(consoleUtilities) },
                 { OptionSettingTypeHint.DotnetPublishSelfContainedBuild, new DotnetPublishSelfContainedBuildCommand(consoleUtilities) },
                 { OptionSettingTypeHint.DotnetPublishBuildConfiguration, new DotnetPublishBuildConfigurationCommand(consoleUtilities) },
-                { OptionSettingTypeHint.DockerExecutionDirectory, new DockerExecutionDirectoryCommand(consoleUtilities) },
+                { OptionSettingTypeHint.DockerExecutionDirectory, new DockerExecutionDirectoryCommand(consoleUtilities, directoryManager) },
                 { OptionSettingTypeHint.DockerBuildArgs, new DockerBuildArgsCommand(consoleUtilities) },
                 { OptionSettingTypeHint.ECSCluster, new ECSClusterCommand(awsResourceQueryer, consoleUtilities) },
                 { OptionSettingTypeHint.ExistingApplicationLoadBalancer, new ExistingApplicationLoadBalancerCommand(awsResourceQueryer, consoleUtilities) },
diff --git a/src/AWS.Deploy.CLI/ConsoleUtilities.cs b/src/AWS.Deploy.CLI/ConsoleUtilities.cs
index 57013da44..97476268e 100644
--- a/src/AWS.Deploy.CLI/ConsoleUtilities.cs
+++ b/src/AWS.Deploy.CLI/ConsoleUtilities.cs
@@ -7,6 +7,7 @@
 using System.Linq;
 using System.Text;
 using AWS.Deploy.Common;
+using AWS.Deploy.Common.IO;
 
 namespace AWS.Deploy.CLI
 {
@@ -35,10 +36,12 @@ T AskUserToChoose<T>(IList<T> options, string title, T defaultValue, string? def
     public class ConsoleUtilities : IConsoleUtilities
     {
         private readonly IToolInteractiveService _interactiveService;
+        private readonly IDirectoryManager _directoryManager;
 
-        public ConsoleUtilities(IToolInteractiveService interactiveService)
+        public ConsoleUtilities(IToolInteractiveService interactiveService, IDirectoryManager directoryManager)
         {
             _interactiveService = interactiveService;
+            _directoryManager = directoryManager;
         }
 
         public Recommendation AskToChooseRecommendation(IList<Recommendation> recommendations)
@@ -311,7 +314,7 @@ public string AskForEC2KeyPairSaveDirectory(string projectPath)
             {
                 var keyPairDirectory = _interactiveService.ReadLine();
                 if (keyPairDirectory != null &&
-                    Directory.Exists(keyPairDirectory))
+                    _directoryManager.Exists(keyPairDirectory))
                 {
                     var projectFolder = new FileInfo(projectPath).Directory;
                     var keyPairDirectoryInfo = new DirectoryInfo(keyPairDirectory);
diff --git a/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs b/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs
index 577135d0b..4be9fd617 100644
--- a/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs
+++ b/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs
@@ -515,7 +515,9 @@ private Orchestrator CreateOrchestrator(SessionState state, IServiceProvider? se
                                     serviceProvider.GetRequiredService<IAWSResourceQueryer>(),
                                     serviceProvider.GetRequiredService<IDeploymentBundleHandler>(),
                                     serviceProvider.GetRequiredService<ILocalUserSettingsEngine>(),
-                                    new DockerEngine.DockerEngine(session.ProjectDefinition),
+                                    new DockerEngine.DockerEngine(
+                                        session.ProjectDefinition,
+                                        serviceProvider.GetRequiredService<IFileManager>()),
                                     serviceProvider.GetRequiredService<ICustomRecipeLocator>(),
                                     new List<string> { RecipeLocator.FindRecipeDefinitionsPath() },
                                     serviceProvider.GetRequiredService<IDirectoryManager>()
diff --git a/src/AWS.Deploy.CLI/Utilities/AssumeRoleMfaTokenCodeCallback.cs b/src/AWS.Deploy.CLI/Utilities/AssumeRoleMfaTokenCodeCallback.cs
index 274c8ea4e..a97677bb8 100644
--- a/src/AWS.Deploy.CLI/Utilities/AssumeRoleMfaTokenCodeCallback.cs
+++ b/src/AWS.Deploy.CLI/Utilities/AssumeRoleMfaTokenCodeCallback.cs
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.Text;
 using Amazon.Runtime;
+using AWS.Deploy.Common.IO;
 
 namespace AWS.Deploy.CLI.Utilities
 {
@@ -15,18 +16,20 @@ internal class AssumeRoleMfaTokenCodeCallback
     {
         private readonly AssumeRoleAWSCredentialsOptions _options;
         private readonly IToolInteractiveService _toolInteractiveService;
+        private readonly IDirectoryManager _directoryManager;
 
-        internal AssumeRoleMfaTokenCodeCallback(IToolInteractiveService toolInteractiveService, AssumeRoleAWSCredentialsOptions options)
+        internal AssumeRoleMfaTokenCodeCallback(IToolInteractiveService toolInteractiveService, IDirectoryManager directoryManager, AssumeRoleAWSCredentialsOptions options)
         {
             _toolInteractiveService = toolInteractiveService;
             _options = options;
+            _directoryManager = directoryManager;
         }
 
         internal string Execute()
         {
             _toolInteractiveService.WriteLine();
             _toolInteractiveService.WriteLine($"Enter MFA code for {_options.MfaSerialNumber}: ");
-            var consoleUtilites = new ConsoleUtilities(_toolInteractiveService);
+            var consoleUtilites = new ConsoleUtilities(_toolInteractiveService, _directoryManager);
             var code = consoleUtilites.ReadSecretFromConsole();
             
             return code;
diff --git a/src/AWS.Deploy.Common/IO/DirectoryManager.cs b/src/AWS.Deploy.Common/IO/DirectoryManager.cs
index be82af6c3..7228d7028 100644
--- a/src/AWS.Deploy.Common/IO/DirectoryManager.cs
+++ b/src/AWS.Deploy.Common/IO/DirectoryManager.cs
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using AWS.Deploy.Common.Utilities;
 
 namespace AWS.Deploy.Common.IO
 {
@@ -35,7 +36,7 @@ public class DirectoryManager : IDirectoryManager
 
         public DirectoryInfo GetDirectoryInfo(string path) => new DirectoryInfo(path);
 
-        public bool Exists(string path) => Directory.Exists(path);
+        public bool Exists(string path) => IsDirectoryValid(path);
 
         public string[] GetFiles(string path, string? searchPattern = null, SearchOption searchOption = SearchOption.TopDirectoryOnly)
             => Directory.GetFiles(path, searchPattern ?? "*", searchOption);
@@ -61,5 +62,16 @@ public string[] GetProjFiles(string path)
         {
             return Directory.GetFiles(path).Where(filePath => _projFileExtensions.Contains(Path.GetExtension(filePath).ToLower())).ToArray();
         }
+
+        private bool IsDirectoryValid(string directoryPath)
+        {
+            if (!PathUtilities.IsPathValid(directoryPath))
+                return false;
+
+            if (!Directory.Exists(directoryPath))
+                return false;
+
+            return true;
+        }
     }
 }
diff --git a/src/AWS.Deploy.Common/IO/FileManager.cs b/src/AWS.Deploy.Common/IO/FileManager.cs
index 4689721e2..5bfd88486 100644
--- a/src/AWS.Deploy.Common/IO/FileManager.cs
+++ b/src/AWS.Deploy.Common/IO/FileManager.cs
@@ -2,8 +2,10 @@
 // SPDX-License-Identifier: Apache-2.0
 
 using System.IO;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
+using AWS.Deploy.Common.Utilities;
 
 namespace AWS.Deploy.Common.IO
 {
@@ -20,7 +22,7 @@ public interface IFileManager
     /// </summary>
     public class FileManager : IFileManager
     {
-        public bool Exists(string path) => File.Exists(path);
+        public bool Exists(string path) => IsFileValid(path);
 
         public Task<string> ReadAllTextAsync(string path) => File.ReadAllTextAsync(path);
 
@@ -28,5 +30,16 @@ public class FileManager : IFileManager
 
         public Task WriteAllTextAsync(string filePath, string contents, CancellationToken cancellationToken) =>
             File.WriteAllTextAsync(filePath, contents, cancellationToken);
+
+        private bool IsFileValid(string filePath)
+        {
+            if (!PathUtilities.IsPathValid(filePath))
+                return false;
+
+            if (!File.Exists(filePath))
+                return false;
+
+            return true;
+        }
     }
 }
diff --git a/src/AWS.Deploy.Common/Utilities/PathUtilities.cs b/src/AWS.Deploy.Common/Utilities/PathUtilities.cs
new file mode 100644
index 000000000..6804200be
--- /dev/null
+++ b/src/AWS.Deploy.Common/Utilities/PathUtilities.cs
@@ -0,0 +1,30 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System.IO;
+using System.Linq;
+
+namespace AWS.Deploy.Common.Utilities
+{
+    public class PathUtilities
+    {
+        public static bool IsPathValid(string path)
+        {
+            path = path.Trim();
+
+            if (string.IsNullOrEmpty(path))
+                return false;
+
+            if (path.StartsWith(@"\\"))
+                return false;
+
+            if (path.Contains("&"))
+                return false;
+
+            if (Path.GetInvalidPathChars().Any(x => path.Contains(x)))
+                return false;
+
+            return true;
+        }
+    }
+}
diff --git a/src/AWS.Deploy.DockerEngine/DockerEngine.cs b/src/AWS.Deploy.DockerEngine/DockerEngine.cs
index c591d3531..140478a28 100644
--- a/src/AWS.Deploy.DockerEngine/DockerEngine.cs
+++ b/src/AWS.Deploy.DockerEngine/DockerEngine.cs
@@ -6,6 +6,7 @@
 using System.IO;
 using System.Linq;
 using AWS.Deploy.Common;
+using AWS.Deploy.Common.IO;
 using Newtonsoft.Json;
 
 namespace AWS.Deploy.DockerEngine
@@ -31,9 +32,10 @@ public interface IDockerEngine
     public class DockerEngine : IDockerEngine
     {
         private readonly ProjectDefinition _project;
+        private readonly IFileManager _fileManager;
         private readonly string _projectPath;
 
-        public DockerEngine(ProjectDefinition project)
+        public DockerEngine(ProjectDefinition project, IFileManager fileManager)
         {
             if (project == null)
             {
@@ -42,6 +44,7 @@ public DockerEngine(ProjectDefinition project)
 
             _project = project;
             _projectPath = project.ProjectPath;
+            _fileManager = fileManager;
         }
 
         /// <summary>
@@ -146,7 +149,7 @@ public void DetermineDockerExecutionDirectory(Recommendation recommendation)
             {
                 var projectFilename = Path.GetFileName(recommendation.ProjectPath);
                 var dockerFilePath = Path.Combine(Path.GetDirectoryName(recommendation.ProjectPath) ?? "", "Dockerfile");
-                if (File.Exists(dockerFilePath))
+                if (_fileManager.Exists(dockerFilePath))
                 {
                     using (var stream = File.OpenRead(dockerFilePath))
                     using (var reader = new StreamReader(stream))
diff --git a/src/AWS.Deploy.Orchestration/Orchestrator.cs b/src/AWS.Deploy.Orchestration/Orchestrator.cs
index 63d5da0aa..fbc7b71dd 100644
--- a/src/AWS.Deploy.Orchestration/Orchestrator.cs
+++ b/src/AWS.Deploy.Orchestration/Orchestrator.cs
@@ -106,7 +106,9 @@ public async Task<List<Recommendation>> GenerateRecommendationsFromSavedDeployme
         {
             if (_session == null)
                 throw new InvalidOperationException($"{nameof(_session)} is null as part of the orchestartor object");
-            if (!Directory.Exists(deploymentProjectPath))
+            if (_directoryManager == null)
+                throw new InvalidOperationException($"{nameof(_directoryManager)} is null as part of the orchestartor object");
+            if (!_directoryManager.Exists(deploymentProjectPath))
                 throw new InvalidCliArgumentException($"The path '{deploymentProjectPath}' does not exists on the file system. Please provide a valid deployment project path and try again.");
 
             var engine = new RecommendationEngine.RecommendationEngine(new List<string> { deploymentProjectPath }, _session);
diff --git a/src/AWS.Deploy.Orchestration/Utilities/ZipFileManager.cs b/src/AWS.Deploy.Orchestration/Utilities/ZipFileManager.cs
index 836f313d2..79ec963e6 100644
--- a/src/AWS.Deploy.Orchestration/Utilities/ZipFileManager.cs
+++ b/src/AWS.Deploy.Orchestration/Utilities/ZipFileManager.cs
@@ -8,6 +8,7 @@
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Threading.Tasks;
+using AWS.Deploy.Common.IO;
 
 namespace AWS.Deploy.Orchestration.Utilities
 {
@@ -19,10 +20,12 @@ public interface IZipFileManager
     public class ZipFileManager : IZipFileManager
     {
         private readonly ICommandLineWrapper _commandLineWrapper;
+        private readonly IFileManager _fileManager;
 
-        public ZipFileManager(ICommandLineWrapper commandLineWrapper)
+        public ZipFileManager(ICommandLineWrapper commandLineWrapper, IFileManager fileManager)
         {
             _commandLineWrapper = commandLineWrapper;
+            _fileManager = fileManager;
         }
 
         public async Task CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
@@ -94,7 +97,7 @@ private IDictionary<string, string> GetFilesToIncludeInArchive(string publishLoc
         /// <returns>The full path to the command if found otherwise it will return null</returns>
         private string? FindExecutableInPath(string command)
         {
-            if (File.Exists(command))
+            if (_fileManager.Exists(command))
                 return Path.GetFullPath(command);
 
             Func<string, string> quoteRemover = x =>
@@ -112,7 +115,7 @@ private IDictionary<string, string> GetFilesToIncludeInArchive(string publishLoc
                 try
                 {
                     var fullPath = Path.Combine(quoteRemover(path), command);
-                    if (File.Exists(fullPath))
+                    if (_fileManager.Exists(fullPath))
                         return fullPath;
                 }
                 catch (Exception)
@@ -121,7 +124,7 @@ private IDictionary<string, string> GetFilesToIncludeInArchive(string publishLoc
                 }
             }
 
-            if (KNOWN_LOCATIONS.ContainsKey(command) && File.Exists(KNOWN_LOCATIONS[command]))
+            if (KNOWN_LOCATIONS.ContainsKey(command) && _fileManager.Exists(KNOWN_LOCATIONS[command]))
                 return KNOWN_LOCATIONS[command];
 
             return null;
diff --git a/test/AWS.Deploy.CLI.UnitTests/ConsoleUtilitiesTests.cs b/test/AWS.Deploy.CLI.UnitTests/ConsoleUtilitiesTests.cs
index cfffcab38..76832b2ab 100644
--- a/test/AWS.Deploy.CLI.UnitTests/ConsoleUtilitiesTests.cs
+++ b/test/AWS.Deploy.CLI.UnitTests/ConsoleUtilitiesTests.cs
@@ -9,11 +9,20 @@
 using Amazon.Runtime;
 using AWS.Deploy.CLI.Utilities;
 using System;
+using AWS.Deploy.Common.IO;
+using AWS.Deploy.CLI.Common.UnitTests.IO;
 
 namespace AWS.Deploy.CLI.UnitTests
 {
     public class ConsoleUtilitiesTests
     {
+        private readonly IDirectoryManager _directoryManager;
+
+        public ConsoleUtilitiesTests()
+        {
+            _directoryManager = new TestDirectoryManager();
+        }
+
         private readonly List<OptionItem> _options = new List<OptionItem>
         {
             new()
@@ -36,7 +45,7 @@ public void AskUserToChooseOrCreateNew()
                 "3",
                 "CustomNewIdentifier"
             });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var userInputConfiguration = new UserInputConfiguration<OptionItem>(
                 option => option.DisplayName,
                 option => option.Identifier.Equals("Identifier2"),
@@ -67,7 +76,7 @@ public void AskUserToChooseOrCreateNewPickExisting()
             {
                 "1"
             });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var userInputConfiguration = new UserInputConfiguration<OptionItem>(
                 option => option.DisplayName,
                 option => option.Identifier.Equals("Identifier2"),
@@ -94,7 +103,7 @@ public void AskUserToChooseOrCreateNewPickExisting()
         public void AskUserToChooseStringsPickDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskUserToChoose(new List<string> { "Option1", "Option2" }, "Title", "Option2");
             Assert.Equal("Option2", selectedValue);
 
@@ -111,7 +120,7 @@ public void AskUserToChooseStringsPickDefault()
         public void AskUserToChooseStringsPicksNoDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "1" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskUserToChoose(new List<string> { "Option1", "Option2" }, "Title", "Option2");
             Assert.Equal("Option1", selectedValue);
         }
@@ -120,7 +129,7 @@ public void AskUserToChooseStringsPicksNoDefault()
         public void AskUserToChooseStringsFirstSelectInvalid()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "a", "10", "1" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskUserToChoose(new List<string> { "Option1", "Option2" }, "Title", "Option2");
             Assert.Equal("Option1", selectedValue);
         }
@@ -129,7 +138,7 @@ public void AskUserToChooseStringsFirstSelectInvalid()
         public void AskUserToChooseStringsNoTitle()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "a", "10", "1" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskUserToChoose(new List<string> { "Option1", "Option2" }, null, "Option2");
             Assert.Equal("Option1", selectedValue);
 
@@ -140,7 +149,7 @@ public void AskUserToChooseStringsNoTitle()
         public void AskUserForValueCanBeSetToEmptyString()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "<reset>" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
 
             var selectedValue =
                 consoleUtilities.AskUserForValue(
@@ -155,7 +164,7 @@ public void AskUserForValueCanBeSetToEmptyString()
         public void AskUserForValueCanBeSetToEmptyStringNoDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "<reset>" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
 
             var selectedValue =
                 consoleUtilities.AskUserForValue(
@@ -170,7 +179,7 @@ public void AskUserForValueCanBeSetToEmptyStringNoDefault()
         public void AskYesNoPickDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { string.Empty });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskYesNoQuestion("Do you want to deploy", YesNo.Yes);
             Assert.Equal(YesNo.Yes, selectedValue);
 
@@ -181,7 +190,7 @@ public void AskYesNoPickDefault()
         public void AskYesNoPickNonDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "n" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskYesNoQuestion("Do you want to deploy", YesNo.Yes);
             Assert.Equal(YesNo.No, selectedValue);
         }
@@ -190,7 +199,7 @@ public void AskYesNoPickNonDefault()
         public void AskYesNoPickNoDefault()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "n" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskYesNoQuestion("Do you want to deploy");
             Assert.Equal(YesNo.No, selectedValue);
 
@@ -201,7 +210,7 @@ public void AskYesNoPickNoDefault()
         public void AskYesNoPickInvalidChoice()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl(new List<string> { "q", "n" });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             var selectedValue = consoleUtilities.AskYesNoQuestion("Do you want to deploy", YesNo.Yes);
             Assert.Equal(YesNo.No, selectedValue);
 
@@ -212,7 +221,7 @@ public void AskYesNoPickInvalidChoice()
         public void DisplayRow()
         {
             var interactiveServices = new TestToolInteractiveServiceImpl();
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
             consoleUtilities.DisplayRow(new[] { ("Hello", 10), ("World", 20) });
 
             Assert.Equal("Hello      | World               ", interactiveServices.OutputMessages[0]);
@@ -230,7 +239,7 @@ public void GetMFACode()
             var interactiveServices = new TestToolInteractiveServiceImpl();
             interactiveServices.QueueConsoleInfos(ConsoleKey.A, ConsoleKey.B, ConsoleKey.C, ConsoleKey.Enter);
 
-            var callback = new AssumeRoleMfaTokenCodeCallback(interactiveServices, options);
+            var callback = new AssumeRoleMfaTokenCodeCallback(interactiveServices, _directoryManager, options);
             var code = callback.Execute();
 
             Assert.Equal("ABC", code);
@@ -254,7 +263,7 @@ public void GetMFACodeWithBackspace()
             var interactiveServices = new TestToolInteractiveServiceImpl();
             interactiveServices.QueueConsoleInfos(ConsoleKey.A, ConsoleKey.B, ConsoleKey.C, ConsoleKey.Backspace, ConsoleKey.D, ConsoleKey.Enter);
 
-            var callback = new AssumeRoleMfaTokenCodeCallback(interactiveServices, options);
+            var callback = new AssumeRoleMfaTokenCodeCallback(interactiveServices, _directoryManager, options);
             var code = callback.Execute();
 
             Assert.Equal("ABD", code);
diff --git a/test/AWS.Deploy.CLI.UnitTests/DockerTests.cs b/test/AWS.Deploy.CLI.UnitTests/DockerTests.cs
index 1c5205198..12dd1abe5 100644
--- a/test/AWS.Deploy.CLI.UnitTests/DockerTests.cs
+++ b/test/AWS.Deploy.CLI.UnitTests/DockerTests.cs
@@ -27,9 +27,11 @@ public async Task DockerGenerate(string topLevelFolder, string projectName)
         {
             var projectPath = ResolvePath(Path.Combine(topLevelFolder, projectName));
 
-            var project = await new ProjectDefinitionParser(new FileManager(), new DirectoryManager()).Parse(projectPath);
+            var fileManager = new FileManager();
 
-            var engine = new DockerEngine.DockerEngine(project);
+            var project = await new ProjectDefinitionParser(fileManager, new DirectoryManager()).Parse(projectPath);
+
+            var engine = new DockerEngine.DockerEngine(project, fileManager);
 
             engine.GenerateDockerFile();
 
diff --git a/test/AWS.Deploy.CLI.UnitTests/RecommendationTests.cs b/test/AWS.Deploy.CLI.UnitTests/RecommendationTests.cs
index 086659e94..71293599d 100644
--- a/test/AWS.Deploy.CLI.UnitTests/RecommendationTests.cs
+++ b/test/AWS.Deploy.CLI.UnitTests/RecommendationTests.cs
@@ -5,6 +5,7 @@
 using System.Linq;
 using System.Threading.Tasks;
 using Amazon.Runtime;
+using AWS.Deploy.CLI.Common.UnitTests.IO;
 using AWS.Deploy.CLI.TypeHintResponses;
 using AWS.Deploy.CLI.UnitTests.Utilities;
 using AWS.Deploy.Common;
@@ -22,6 +23,13 @@ namespace AWS.Deploy.CLI.UnitTests
     public class RecommendationTests
     {
         private OrchestratorSession _session;
+        private readonly IDirectoryManager _directoryManager;
+
+        public RecommendationTests()
+        {
+            _directoryManager = new TestDirectoryManager();
+        }
+
         private async Task<RecommendationEngine> BuildRecommendationEngine(string testProjectName)
         {
             var fullPath = SystemIOUtilities.ResolvePath(testProjectName);
@@ -128,7 +136,7 @@ public async Task ResetOptionSettingValue_Int()
                 "<reset>"
             });
 
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
 
             var engine = await BuildRecommendationEngine("WebAppNoDockerFile");
 
@@ -155,7 +163,7 @@ public async Task ResetOptionSettingValue_String()
             {
                 "<reset>"
             });
-            var consoleUtilities = new ConsoleUtilities(interactiveServices);
+            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);
 
             var engine = await BuildRecommendationEngine("WebAppNoDockerFile");
 

From 4f9863624d4f1b5986e1330447a67e05a12f4960 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <kmalhar@amazon.com>
Date: Tue, 31 Aug 2021 16:25:47 -0400
Subject: [PATCH 5/5] fix: Fixes the re-deployment experience using the ECS
 Fargate recipe

---
 src/AWS.Deploy.Recipes.CDK.Common/CDKRecipeSetup.cs   |  9 ++++++++-
 .../Configurations/AutoScalingConfiguration.cs        |  2 +-
 .../WebAppWithDockerFileTests.cs                      | 11 +++++++++++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/AWS.Deploy.Recipes.CDK.Common/CDKRecipeSetup.cs b/src/AWS.Deploy.Recipes.CDK.Common/CDKRecipeSetup.cs
index 06c5e2d3d..6d85bffb4 100644
--- a/src/AWS.Deploy.Recipes.CDK.Common/CDKRecipeSetup.cs
+++ b/src/AWS.Deploy.Recipes.CDK.Common/CDKRecipeSetup.cs
@@ -5,6 +5,7 @@
 using Microsoft.Extensions.Configuration;
 
 using Amazon.CDK;
+using System.Text.Json.Serialization;
 
 namespace AWS.Deploy.Recipes.CDK.Common
 {
@@ -27,7 +28,13 @@ public static void RegisterStack<C>(Stack stack, IRecipeProps<C> recipeConfigura
             stack.Tags.SetTag(Constants.CloudFormationIdentifier.STACK_TAG, $"{recipeConfiguration.RecipeId}");
 
             // Serializes all AWS .NET deployment tool settings.
-            var json = JsonSerializer.Serialize(recipeConfiguration.Settings, new JsonSerializerOptions { WriteIndented = false });
+            var json = JsonSerializer.Serialize(
+                recipeConfiguration.Settings,
+                new JsonSerializerOptions
+                {
+                    WriteIndented = false,
+                    Converters = { new JsonStringEnumConverter() }
+                });
 
             Dictionary<string, object> metadata;
             if(stack.TemplateOptions.Metadata?.Count > 0)
diff --git a/src/AWS.Deploy.Recipes/CdkTemplates/AspNetAppEcsFargate/Generated/Configurations/AutoScalingConfiguration.cs b/src/AWS.Deploy.Recipes/CdkTemplates/AspNetAppEcsFargate/Generated/Configurations/AutoScalingConfiguration.cs
index fef28be43..d1b887216 100644
--- a/src/AWS.Deploy.Recipes/CdkTemplates/AspNetAppEcsFargate/Generated/Configurations/AutoScalingConfiguration.cs
+++ b/src/AWS.Deploy.Recipes/CdkTemplates/AspNetAppEcsFargate/Generated/Configurations/AutoScalingConfiguration.cs
@@ -19,7 +19,7 @@ public class AutoScalingConfiguration
 
         public enum ScalingTypeEnum { Cpu, Memory, Request }
 
-        public ScalingTypeEnum ScalingType { get; set; } = ScalingTypeEnum.Cpu;
+        public ScalingTypeEnum? ScalingType { get; set; }
 
 
 
diff --git a/test/AWS.Deploy.CLI.IntegrationTests/WebAppWithDockerFileTests.cs b/test/AWS.Deploy.CLI.IntegrationTests/WebAppWithDockerFileTests.cs
index cf98e46c6..016ff9de1 100644
--- a/test/AWS.Deploy.CLI.IntegrationTests/WebAppWithDockerFileTests.cs
+++ b/test/AWS.Deploy.CLI.IntegrationTests/WebAppWithDockerFileTests.cs
@@ -102,6 +102,17 @@ public async Task DefaultConfigurations()
             var listDeployStdOut = _interactiveService.StdOutReader.ReadAllLines();
             Assert.Contains(listDeployStdOut, (deployment) => _stackName.Equals(deployment));
 
+            // Arrange input for re-deployment
+            await _interactiveService.StdInWriter.WriteAsync(Environment.NewLine); // Select default option settings
+            await _interactiveService.StdInWriter.FlushAsync();
+
+            // Perform re-deployment
+            deployArgs = new[] { "deploy", "--project-path", projectPath, "--stack-name", _stackName, "--diagnostics" };
+            var returnCode  = await _app.Run(deployArgs);
+            Assert.Equal(CommandReturnCodes.SUCCESS, returnCode);
+            Assert.Equal(StackStatus.UPDATE_COMPLETE, await _cloudFormationHelper.GetStackStatus(_stackName));
+            Assert.Equal("ACTIVE", cluster.Status);
+
             // Arrange input for delete
             await _interactiveService.StdInWriter.WriteAsync("y"); // Confirm delete
             await _interactiveService.StdInWriter.FlushAsync();