diff --git a/lib/GHCup.hs b/lib/GHCup.hs
index dde8072d3a84d8ae0ce9b5a2a4a303564e35ac17..7605d656d574f5d05bdef6cafd30e67b66af6481 100644
--- a/lib/GHCup.hs
+++ b/lib/GHCup.hs
@@ -53,6 +53,7 @@ import           Prelude                 hiding ( abs
                                                 )
 import           System.IO.Error
 import           System.Posix.FilePath          ( getSearchPath )
+import           System.Posix.Files.ByteString
 
 import qualified Data.ByteString               as B
 import qualified Data.Map.Strict               as Map
@@ -694,6 +695,11 @@ upgradeGHCup dls mtarget = do
   tmp   <- lift withGHCupTmpDir
   let fn = [rel|ghcup|]
   p <- liftE $ download dli tmp (Just fn)
+  let fileMode' =
+        newFilePerms
+          `unionFileModes` ownerExecuteMode
+          `unionFileModes` groupExecuteMode
+          `unionFileModes` otherExecuteMode
   case mtarget of
     Nothing -> do
       dest <- liftIO $ ghcupBinDir
@@ -701,11 +707,13 @@ upgradeGHCup dls mtarget = do
       handleIO (throwE . CopyError . show) $ liftIO $ copyFile p
                                                                (dest </> fn)
                                                                Overwrite
+      liftIO $ setFileMode (toFilePath (dest </> fn)) fileMode'
     Just fullDest -> do
       liftIO $ hideError NoSuchThing $ deleteFile fullDest
       handleIO (throwE . CopyError . show) $ liftIO $ copyFile p
                                                                fullDest
                                                                Overwrite
+      liftIO $ setFileMode (toFilePath fullDest) fileMode'
   pure latestVer