Skip to content

Commit

Permalink
Disable implicit execution of batch files (#14557)
Browse files Browse the repository at this point in the history
Co-authored-by: Oleh Prypin <[email protected]>
  • Loading branch information
straight-shoota and oprypin authored May 8, 2024
1 parent 3eab3e4 commit 4a4952c
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
13 changes: 13 additions & 0 deletions spec/std/process_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,19 @@ pending_interpreted describe: Process do
output.should eq "`echo hi`\n"
end

describe "does not execute batch files" do
%w[.bat .Bat .BAT .cmd .cmD .CmD].each do |ext|
it ext do
with_tempfile "process_run#{ext}" do |path|
File.write(path, "echo '#{ext}'\n")
expect_raises {{ flag?(:win32) ? File::BadExecutableError : File::AccessDeniedError }}, "Error executing process" do
Process.run(path)
end
end
end
end
end

describe "environ" do
it "clears the environment" do
value = Process.run(*print_env_command, clear_env: true) do |proc|
Expand Down
10 changes: 10 additions & 0 deletions src/crystal/system/win32/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,16 @@ struct Crystal::System::Process
end
command
else
# Disable implicit execution of batch files (https://github.com/crystal-lang/crystal/issues/14536)
#
# > `CreateProcessW()` implicitly spawns `cmd.exe` when executing batch files (`.bat`, `.cmd`, etc.), even if the application didn’t specify them in the command line.
# > The problem is that the `cmd.exe` has complicated parsing rules for the command arguments, and programming language runtimes fail to escape the command arguments properly.
# > Because of this, it’s possible to inject commands if someone can control the part of command arguments of the batch file.
# https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/
if command.byte_slice?(-4, 4).try(&.downcase).in?(".bat", ".cmd")
raise ::File::Error.from_os_error("Error executing process", WinError::ERROR_BAD_EXE_FORMAT, file: command)
end

command_args = [command]
command_args.concat(args) if args
command_args
Expand Down

0 comments on commit 4a4952c

Please sign in to comment.