-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Use %COMSPEC%
as the shell in Process.new(shell: true)
#13567
base: master
Are you sure you want to change the base?
Use %COMSPEC%
as the shell in Process.new(shell: true)
#13567
Conversation
Right now the command is not escaped at all. It seems this would suffice except for newlines? Should we do it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change gets a veto from me.
I have expressed on the issue that this is not the way to go. Let me elaborate further.
Upsides of this change:
- You can write
echo %cd%
instead ofcmd /c echo %cd%
Downsides of this change:
- There is no longer any way to pass a native unprocessed arg string to a Windows process, it has to be one produced from a list of strings or from
cmd.exe
. This makes some valid exotic inputs non-representable. - There is no longer any part of standard library that makes sense to use with the output of
Process.quote_windows
. It may as well be deprecated. Any usages ofProcess.quote_windows
(or any.quote
on Windows) that exist in Crystal's own codebase (except this single one insrc/crystal/system/win32/process.cr
) are now wrong and dangerous. Process.quote
used to be always the right thing to put intosystem( )
/` `
, now it is dangerous on Windows. There is no possible replacement for it with this change. There is no way to safely quote anything.- The compiler immediately receives security holes. For example:
- Any percent sign anywhere in macros' args can now expand an environment variable, or any arbitrary command injection is possible:
command = "#{Process.quote(original_filename)} #{Process.quote(run_args)}" - Surprise variable expansion and all kinds of things in unexpected places, like this output filename:
crystal/src/compiler/crystal/compiler.cr
Line 342 in 77c8cee
output_arg = Process.quote_windows("/Fe#{output_filename}")
- Any percent sign anywhere in macros' args can now expand an environment variable, or any arbitrary command injection is possible:
Actually the article seems to suggest that in cmd shell, the If so, this part of my message is wrong:
Then just updating the |
So I suppose to move this further, we should adapt Then we can merge this and hopefully escaping should work correctly? We'll probably need some specs for that. |
If I understand correctly, you want Applying IMHO if security is a concern, one simply should not use the backtick in the first place. It has never occurred to me that the standard library should guarantee |
I'm not quite sure I can grasp the dilemma here.
It would seem that
Whether that promise was correct in the first place might be a different question but I suppose we should try to follow it.
Could you elaborate on why such use cases would break? |
There is indeed one breakage. When the compiler prepares the linker arguments for MSVC, if they are too long they are written to |
Resolves #9030. Also effectively confirms in the specs that passing
args
withshell: true
is not allowed.Also effectively closes #12873, as
Process.run("filedoesnotexist", shell: true)
will now returnProcess::Status[1]
instead of raising. (The exit codes are still different across platforms but I doubt anything further could be done about that.)Unsetting
%COMSPEC%
is now a hard error, although under normal circumstances nobody should attempt to do that on Windows. It is needed because we do not look upcmd.exe
in%PATH%
, but the system drive's letter name is not fixed, i.e. we cannot simply assumeC:\...\cmd.exe
is correct.