Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call purescript with the shell enabled on Windows, as a workaround for CVE-2024-27980 #1308

Merged
merged 2 commits into from
Jan 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/Spago/Cmd.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Node.Library.Execa as Execa
import Node.Platform as Platform
import Node.Process as Process
import Partial.Unsafe (unsafeCrashWith, unsafePartial)
import Unsafe.Coerce (unsafeCoerce)

data StdinConfig
= StdinPipeParent
Expand Down Expand Up @@ -77,6 +78,7 @@ type ExecOptions =
, pipeStdout :: Boolean
, pipeStderr :: Boolean
, cwd :: Maybe FilePath
, shell :: Boolean
}

defaultExecOptions :: ExecOptions
Expand All @@ -85,6 +87,7 @@ defaultExecOptions =
, pipeStdout: true
, pipeStderr: true
, cwd: Nothing
, shell: false
}

spawn :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m Execa.ExecaProcess
Expand All @@ -94,7 +97,18 @@ spawn cmd args opts = liftAff do
StdinPipeParent -> Just inherit
StdinWrite _ -> Just pipe
StdinNewPipe -> Just pipe
subprocess <- Execa.execa cmd args (_ { cwd = opts.cwd, stdin = stdinOpt, stdout = Just pipe, stderr = Just pipe })
subprocess <- Execa.execa cmd args
( _
{ cwd = opts.cwd
, stdin = stdinOpt
, stdout = Just pipe
, stderr = Just pipe
, shell = case opts.shell of
-- TODO: execa doesn't support the boolean option yet
true -> Just (unsafeCoerce true)
false -> Nothing
}
)

case opts.pipeStdin of
StdinWrite s | Just { writeUtf8End } <- subprocess.stdin -> writeUtf8End s
Expand Down Expand Up @@ -189,22 +203,22 @@ getExecutable command =
Just Platform.Win32 -> do
-- On Windows, we often need to call the `.cmd` version
let cmd1 = mkCmd command (Just "cmd")
askVersion cmd1 >>= case _ of
askVersion cmd1 true >>= case _ of
Right r -> pure { cmd: cmd1, output: r.stdout }
Left r -> do
let cmd2 = mkCmd command Nothing
logDebug [ "Failed to find purs.cmd. Trying with just purs...", show r.message ]
askVersion cmd2 >>= case _ of
askVersion cmd2 false >>= case _ of
Right r' -> pure { cmd: cmd2, output: r'.stdout }
Left r' -> complain r'
_ -> do
-- On other platforms, we just call `purs`
let cmd1 = mkCmd command Nothing
askVersion cmd1 >>= case _ of
askVersion cmd1 false >>= case _ of
Right r -> pure { cmd: cmd1, output: r.stdout }
Left r -> complain r
where
askVersion cmd = exec cmd [ "--version" ] defaultExecOptions { pipeStdout = false, pipeStderr = false }
askVersion cmd shell = exec cmd [ "--version" ] defaultExecOptions { pipeStdout = false, pipeStderr = false, shell = shell }

mkCmd cmd maybeExtension = cmd <> maybe "" (append ".") maybeExtension

Expand Down
Loading