diff --git a/cabal-testsuite/PackageTests/ExternalCommand/cabal.out b/cabal-testsuite/PackageTests/ExternalCommand/cabal.out
new file mode 100644
index 0000000000000000000000000000000000000000..1c4c24db55c1f7af2090527e26e4646dbab0a3e1
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/cabal.out
@@ -0,0 +1,8 @@
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - setup-test-0.1.0.0 (exe:cabal-aaaa) (first run)
+Configuring executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Preprocessing executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Building executable 'cabal-aaaa' for setup-test-0.1.0.0...
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/cabal.project b/cabal-testsuite/PackageTests/ExternalCommand/cabal.project
new file mode 100644
index 0000000000000000000000000000000000000000..1a33bb5a25ecb4a66a52abc8d74dc62251591ac0
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/cabal.project
@@ -0,0 +1 @@
+packages: setup-test/
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/cabal.test.hs b/cabal-testsuite/PackageTests/ExternalCommand/cabal.test.hs
new file mode 100644
index 0000000000000000000000000000000000000000..850c8bfbcec25a11a20012503646c02ae05e48a7
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/cabal.test.hs
@@ -0,0 +1,37 @@
+import Test.Cabal.Prelude
+import qualified System.Process as Process
+import Control.Concurrent (threadDelay)
+import System.Directory (removeFile)
+import Control.Exception (catch, throwIO)
+import System.IO.Error (isDoesNotExistError)
+import qualified Data.Time.Clock as Time
+import qualified Data.Time.Format as Time
+import Data.Maybe
+import System.Environment
+
+main = do
+  cabalTest $ do
+    res <- cabalWithStdin "v2-build" ["all"] ""
+    exe_path <- withPlan $ planExePath "setup-test" "cabal-aaaa"
+    env <- getTestEnv
+    path <- liftIO $ getEnv "PATH"
+    let newpath = takeDirectory exe_path ++ ":" ++ path
+    let new_env = (("PATH", Just newpath) : (testEnvironment env))
+    withEnv new_env $ do
+      res <- cabal_raw_action ["aaaa"] (\h -> () <$ Process.waitForProcess h)
+      assertOutputContains "aaaa" res
+
+
+cabal_raw_action :: [String] -> (Process.ProcessHandle -> IO ()) -> TestM Result
+cabal_raw_action args action = do
+    configured_prog <- requireProgramM cabalProgram
+    env <- getTestEnv
+    r <- liftIO $ runAction (testVerbosity env)
+                 (Just (testCurrentDir env))
+                 (testEnvironment env)
+                 (programPath configured_prog)
+                 args
+                 Nothing
+                 action
+    recordLog r
+    requireSuccess r
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/setup-test/AAAA.hs b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/AAAA.hs
new file mode 100644
index 0000000000000000000000000000000000000000..5bee0ebbef119826187981ca2afd66fd3b850e0b
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/AAAA.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main = do
+  putStrLn "aaaa"
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/setup-test/CHANGELOG.md b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..7ae8ff6113dfd7555afef16a6ff3747eed5fadba
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for setup-test
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/setup-test/LICENSE b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..cd8ad2ac8aef979cdc063ca6db3200486b55c74c
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2023, Matthew Pickering
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Matthew Pickering nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cabal-testsuite/PackageTests/ExternalCommand/setup-test/setup-test.cabal b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/setup-test.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..8deb0577a16810696dfaa057356fab69d203c715
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommand/setup-test/setup-test.cabal
@@ -0,0 +1,25 @@
+cabal-version:      3.0
+name:               setup-test
+version:            0.1.0.0
+-- synopsis:
+-- description:
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Matthew Pickering
+maintainer:         matthewtpickering@gmail.com
+-- copyright:
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+-- extra-source-files:
+
+common warnings
+    ghc-options: -Wall
+
+executable cabal-aaaa
+    import:           warnings
+    main-is: AAAA.hs
+    -- other-modules:
+    -- other-extensions:
+    build-depends:    base
+    hs-source-dirs:   .
+    default-language: Haskell2010
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.out b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.out
new file mode 100644
index 0000000000000000000000000000000000000000..1c4c24db55c1f7af2090527e26e4646dbab0a3e1
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.out
@@ -0,0 +1,8 @@
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - setup-test-0.1.0.0 (exe:cabal-aaaa) (first run)
+Configuring executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Preprocessing executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Building executable 'cabal-aaaa' for setup-test-0.1.0.0...
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.project b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.project
new file mode 100644
index 0000000000000000000000000000000000000000..1a33bb5a25ecb4a66a52abc8d74dc62251591ac0
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.project
@@ -0,0 +1 @@
+packages: setup-test/
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.test.hs b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.test.hs
new file mode 100644
index 0000000000000000000000000000000000000000..891c9e43d4b9d09e3e16438962a0b7ce48232bab
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/cabal.test.hs
@@ -0,0 +1,39 @@
+import Test.Cabal.Prelude
+import qualified System.Process as Process
+import Control.Concurrent (threadDelay)
+import System.Directory (removeFile)
+import Control.Exception (catch, throwIO)
+import System.IO.Error (isDoesNotExistError)
+import qualified Data.Time.Clock as Time
+import qualified Data.Time.Format as Time
+import Data.Maybe
+import System.Environment
+
+main = do
+  cabalTest $ expectBroken 9402 $ do
+    res <- cabalWithStdin "v2-build" ["all"] ""
+    exe_path <- withPlan $ planExePath "setup-test" "cabal-aaaa"
+    env <- getTestEnv
+    path <- liftIO $ getEnv "PATH"
+    let newpath = takeDirectory exe_path ++ ":" ++ path
+    let new_env = (("OTHER_VAR", Just "is set") : ("PATH", Just newpath) : (testEnvironment env))
+
+    withEnv new_env $ do
+      res <- cabal_raw_action ["aaaa"] (\h -> () <$ Process.waitForProcess h)
+      assertOutputContains "cabal-install" res
+      assertOutputContains "is set" res
+
+
+cabal_raw_action :: [String] -> (Process.ProcessHandle -> IO ()) -> TestM Result
+cabal_raw_action args action = do
+    configured_prog <- requireProgramM cabalProgram
+    env <- getTestEnv
+    r <- liftIO $ runAction (testVerbosity env)
+                 (Just (testCurrentDir env))
+                 (testEnvironment env)
+                 (programPath configured_prog)
+                 args
+                 Nothing
+                 action
+    recordLog r
+    requireSuccess r
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/AAAA.hs b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/AAAA.hs
new file mode 100644
index 0000000000000000000000000000000000000000..99af61e9c03607724e687afea08a0760c79b3a18
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/AAAA.hs
@@ -0,0 +1,11 @@
+module Main where
+
+import System.Environment
+import System.Process
+
+main = do
+  cabal_proc <- getEnv "CABAL"
+  other_var <- getEnv "OTHER_VAR"
+  putStrLn ("OTHER_VAR is set to: " ++ other_var)
+  callProcess cabal_proc ["--version"]
+
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/CHANGELOG.md b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..7ae8ff6113dfd7555afef16a6ff3747eed5fadba
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for setup-test
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/LICENSE b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..cd8ad2ac8aef979cdc063ca6db3200486b55c74c
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2023, Matthew Pickering
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Matthew Pickering nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/setup-test.cabal b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/setup-test.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..a5feea69112075069aec101457c867353702abf1
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandEnv/setup-test/setup-test.cabal
@@ -0,0 +1,25 @@
+cabal-version:      3.0
+name:               setup-test
+version:            0.1.0.0
+-- synopsis:
+-- description:
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Matthew Pickering
+maintainer:         matthewtpickering@gmail.com
+-- copyright:
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+-- extra-source-files:
+
+common warnings
+    ghc-options: -Wall
+
+executable cabal-aaaa
+    import:           warnings
+    main-is: AAAA.hs
+    -- other-modules:
+    -- other-extensions:
+    build-depends:    base, process
+    hs-source-dirs:   .
+    default-language: Haskell2010
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.out b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.out
new file mode 100644
index 0000000000000000000000000000000000000000..0a3edf696f924f70728cc1a9eeb2722a4b9d4f35
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.out
@@ -0,0 +1,12 @@
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - setup-test-0.1.0.0 (exe:cabal-aaaa) (first run)
+ - setup-test-0.1.0.0 (exe:setup) (first run)
+Configuring executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Preprocessing executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Building executable 'cabal-aaaa' for setup-test-0.1.0.0...
+Configuring executable 'setup' for setup-test-0.1.0.0...
+Preprocessing executable 'setup' for setup-test-0.1.0.0...
+Building executable 'setup' for setup-test-0.1.0.0...
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.project b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.project
new file mode 100644
index 0000000000000000000000000000000000000000..1a33bb5a25ecb4a66a52abc8d74dc62251591ac0
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.project
@@ -0,0 +1 @@
+packages: setup-test/
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.test.hs b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.test.hs
new file mode 100644
index 0000000000000000000000000000000000000000..a3a8acfa5c740461f0866defce2ee8f3b4d2beeb
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/cabal.test.hs
@@ -0,0 +1,37 @@
+import Test.Cabal.Prelude
+import qualified System.Process as Process
+import Control.Concurrent (threadDelay)
+import System.Directory (removeFile)
+import Control.Exception (catch, throwIO)
+import System.IO.Error (isDoesNotExistError)
+import qualified Data.Time.Clock as Time
+import qualified Data.Time.Format as Time
+import Data.Maybe
+import System.Environment
+
+main = do
+  cabalTest $ expectBroken 9404 $ do
+    res <- cabalWithStdin "v2-build" ["all"] ""
+    exe_path <- withPlan $ planExePath "setup-test" "cabal-aaaa"
+    env <- getTestEnv
+    path <- liftIO $ getEnv "PATH"
+    let newpath = takeDirectory exe_path ++ ":" ++ path
+    let new_env = (("PATH", Just newpath) : (testEnvironment env))
+    withEnv new_env $ do
+      res <- cabal_raw_action ["help", "aaaa"] (\h -> () <$ Process.waitForProcess h)
+      assertOutputContains "I am helping with the aaaa command" res
+
+
+cabal_raw_action :: [String] -> (Process.ProcessHandle -> IO ()) -> TestM Result
+cabal_raw_action args action = do
+    configured_prog <- requireProgramM cabalProgram
+    env <- getTestEnv
+    r <- liftIO $ runAction (testVerbosity env)
+                 (Just (testCurrentDir env))
+                 (testEnvironment env)
+                 (programPath configured_prog)
+                 args
+                 Nothing
+                 action
+    recordLog r
+    requireSuccess r
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/AAAA.hs b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/AAAA.hs
new file mode 100644
index 0000000000000000000000000000000000000000..10fe05988d80a1ccfe8fd678c9ed66e374fd78a7
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/AAAA.hs
@@ -0,0 +1,9 @@
+module Main where
+
+import System.Environment
+
+main = do
+  args <- getArgs
+  case args of
+    ["--help"] -> putStrLn "I am helping with the aaaa command"
+    _ -> putStrLn "aaaa"
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/CHANGELOG.md b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..7ae8ff6113dfd7555afef16a6ff3747eed5fadba
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for setup-test
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/LICENSE b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..cd8ad2ac8aef979cdc063ca6db3200486b55c74c
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2023, Matthew Pickering
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Matthew Pickering nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/setup-test.cabal b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/setup-test.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..8deb0577a16810696dfaa057356fab69d203c715
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandHelp/setup-test/setup-test.cabal
@@ -0,0 +1,25 @@
+cabal-version:      3.0
+name:               setup-test
+version:            0.1.0.0
+-- synopsis:
+-- description:
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Matthew Pickering
+maintainer:         matthewtpickering@gmail.com
+-- copyright:
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+-- extra-source-files:
+
+common warnings
+    ghc-options: -Wall
+
+executable cabal-aaaa
+    import:           warnings
+    main-is: AAAA.hs
+    -- other-modules:
+    -- other-extensions:
+    build-depends:    base
+    hs-source-dirs:   .
+    default-language: Haskell2010
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/LICENSE b/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/Main.hs b/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/Main.hs
new file mode 100644
index 0000000000000000000000000000000000000000..b3fcf560699d8f38981292c64b81af24c2bd7d29
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/Main.hs
@@ -0,0 +1,3 @@
+module Main where
+
+main = putStrLn "aaaa"
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/aaaa.cabal b/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/aaaa.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..cafeabd58556090b46d33ed55e64fdb4585980da
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/aaaa/aaaa.cabal
@@ -0,0 +1,22 @@
+cabal-version:      3.0
+name:               aaaa
+version:            0.1.0.0
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Matthew Pickering
+maintainer:         matthewtpickering@gmail.com
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+-- extra-source-files:
+
+common warnings
+    ghc-options: -Wall
+
+executable cabal-aaaa
+    import:           warnings
+    main-is:          Main.hs
+    -- other-modules:
+    -- other-extensions:
+    build-depends:    base
+    hs-source-dirs:   .
+    default-language: Haskell2010
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/CHANGELOG.md b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..063fef7c698c11056b6c119930de6b75dcc0cf20
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for custom
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/LICENSE b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..cd8ad2ac8aef979cdc063ca6db3200486b55c74c
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2023, Matthew Pickering
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Matthew Pickering nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/Setup.hs b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/Setup.hs
new file mode 100644
index 0000000000000000000000000000000000000000..e8efd11bddbcc587bf8ddd9f5713010b7e5c67a6
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/Setup.hs
@@ -0,0 +1,3 @@
+module Main where
+import Distribution.Simple
+main = defaultMain
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/custom.cabal b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/custom.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..0dbc609439b7413a355e1e0dbb121bed2791f402
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/custom/custom.cabal
@@ -0,0 +1,29 @@
+cabal-version:      3.0
+name:               custom
+version:            0.1.0.0
+-- synopsis:
+-- description:
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Matthew Pickering
+maintainer:         matthewtpickering@gmail.com
+-- copyright:
+build-type:         Custom
+extra-doc-files:    CHANGELOG.md
+-- extra-source-files:
+
+common warnings
+    ghc-options: -Wall
+
+custom-setup
+  build-depends: base, Cabal
+
+library
+    import:           warnings
+    exposed-modules:  MyLib
+    -- other-modules:
+    -- other-extensions:
+    build-depends:    base
+    hs-source-dirs:   src
+    default-language: Haskell2010
+
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.cabal.hs b/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.cabal.hs
new file mode 100644
index 0000000000000000000000000000000000000000..7de624d45308db16e16b630f04e985997e45ad8b
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.cabal.hs
@@ -0,0 +1,17 @@
+import Test.Cabal.Prelude
+import System.Environment
+
+main = setupTest $ expectBroken 9403 $ do
+        withPackageDb $ do
+          withDirectory "aaaa" $ setup_install []
+          r <- runInstalledExe' "cabal-aaaa" []
+          env <- getTestEnv
+          path <- liftIO $ getEnv "PATH"
+          let exe_path = testPrefixDir env </> "bin"
+          let newpath = exe_path ++ ":" ++ path
+          let new_env = (("PATH", Just newpath) : (testEnvironment env))
+          withEnv new_env $ do
+            res <- withDirectory "custom" $ setup' "aaaa" []
+            assertOutputContains "did you mean" res
+
+
diff --git a/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.out b/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.out
new file mode 100644
index 0000000000000000000000000000000000000000..e234d5e2a484e0da024865e608e1abbb7f1af093
--- /dev/null
+++ b/cabal-testsuite/PackageTests/ExternalCommandSetup/setup.out
@@ -0,0 +1,22 @@
+# Setup configure
+Configuring aaaa-0.1.0.0...
+# Setup build
+Preprocessing executable 'aaaa' for aaaa-0.1.0.0...
+Building executable 'aaaa' for aaaa-0.1.0.0...
+# Setup copy
+Installing executable aaaa in <PATH>
+Warning: The directory <ROOT>/setup.dist/usr/bin is not in the system search path.
+# Setup register
+Package contains no library to register: aaaa-0.1.0.0...
+# aaaa
+aaaa
+# Setup configure
+Warning: custom.cabal:19:3: Unknown field: "build-depends"
+Configuring custom-0.1.0.0...
+# Setup build
+Preprocessing library for custom-0.1.0.0...
+Building library for custom-0.1.0.0...
+# Setup copy
+Installing library in <PATH>
+# Setup register
+Registering library for custom-0.1.0.0...
diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs
index 757a71aefb7b0cc206ff9093835c677d76f39998..2977a9270cc99341062bcd6e5f5556d16df4d9a2 100644
--- a/cabal-testsuite/src/Test/Cabal/Prelude.hs
+++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs
@@ -358,15 +358,21 @@ runPlanExe pkg_name cname args = void $ runPlanExe' pkg_name cname args
 runPlanExe' :: String {- package name -} -> String {- component name -}
             -> [String] -> TestM Result
 runPlanExe' pkg_name cname args = do
+    exePath <- planExePath pkg_name cname
+    defaultRecordMode RecordAll $ do
+    recordHeader [pkg_name, cname]
+    runM exePath args Nothing
+
+planExePath :: String {- package name -} -> String {- component name -}
+            -> TestM FilePath
+planExePath pkg_name cname = do
     Just plan <- testPlan `fmap` getTestEnv
     let distDirOrBinFile = planDistDir plan (mkPackageName pkg_name)
                                (CExeName (mkUnqualComponentName cname))
         exePath = case distDirOrBinFile of
           DistDir dist_dir -> dist_dir </> "build" </> cname </> cname
           BinFile bin_file -> bin_file
-    defaultRecordMode RecordAll $ do
-    recordHeader [pkg_name, cname]
-    runM exePath args Nothing
+    return exePath
 
 ------------------------------------------------------------------------
 -- * Running ghc-pkg