| This is a weird coincidence – I ran into this exact problem two days ago, the day before the post was published. I was just trying to write a simple batch script that accepted filenames as arguments and was surprised to find that there is no safe way to do so, as they're always passed through shell expansion, so if you have a filename like "foo %PATH% bar.txt" (which is allowed) the script will receive it with the PATH variable expanded and cannot get at the actual filename. Also, passing arguments to programs is unsafe on Windows even if you don't go through the shell, because the quoting rules are entirely up to the program being invoked. The CreateProcess function[0] accepts a string, not an array, so you have to quote the arguments – but you can't do this quoting correctly unless you know exactly what program you're invoking and what grammar it has chosen for parsing its lpCommandLine string. The article mentions that "many programming languages guarantee that the command arguments are escaped properly", but there is no universal "escaped properly" on Windows. There is escaped properly for the C runtime's parser[1], or escaped properly for CommandLineToArgv[2] which parses "in a way that is similar to" the C runtime, or escaped properly for .NET which has its own set of rules[3] – but there is no guarantee that any particular program is using any of these ways; any program can use whatever rules it likes! Raymond Chen has written[4] about this as well. PowerShell has an interesting workaround[5] of sorts: If you specify "-EncodedCommand" and "-EncodedArguments" it lets you pass base64-encoded strings when you "require complex quotation marks or curly braces". [0] https://learn.microsoft.com/en-us/windows/win32/api/processt... [1] https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-c... [2] https://learn.microsoft.com/en-us/windows/win32/api/shellapi... [3] https://learn.microsoft.com/en-us/dotnet/api/system.environm... [4] https://devblogs.microsoft.com/oldnewthing/20100917-00/?p=12... [5] https://learn.microsoft.com/en-us/powershell/module/microsof... |
Here's my try in ruby from a prior life: https://github.com/chef/mixlib-shellout/blob/main/lib/mixlib...