|
88 | 88 | //! assert_eq!(b"test", output.stdout.as_slice());
|
89 | 89 | //! ```
|
90 | 90 | //!
|
| 91 | +//! # Windows argument splitting |
| 92 | +//! |
| 93 | +//! On Unix systems arguments are passed to a new process as an array of strings |
| 94 | +//! but on Windows arguments are passed as a single commandline string and it's |
| 95 | +//! up to the child process to parse it into an array. Therefore the parent and |
| 96 | +//! child processes must agree on how the commandline string is encoded. |
| 97 | +//! |
| 98 | +//! Most programs use the standard C run-time `argv`, which in practice results |
| 99 | +//! in consistent argument handling. However some programs have their own way of |
| 100 | +//! parsing the commandline string. In these cases using [`arg`] or [`args`] may |
| 101 | +//! result in the child process seeing a different array of arguments then the |
| 102 | +//! parent process intended. |
| 103 | +//! |
| 104 | +//! Two ways of mitigating this are: |
| 105 | +//! |
| 106 | +//! * Validate untrusted input so that only a safe subset is allowed. |
| 107 | +//! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping |
| 108 | +//! rules used by [`arg`] so should be used with due caution. |
| 109 | +//! |
| 110 | +//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially |
| 111 | +//! vulnerable to malicious input as they may be used to run arbitrary shell |
| 112 | +//! commands. Untrusted arguments should be restricted as much as possible. |
| 113 | +//! For examples on handling this see [`raw_arg`]. |
| 114 | +//! |
| 115 | +//! ### Bat file special handling |
| 116 | +//! |
| 117 | +//! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to |
| 118 | +//! spawn new processes. An undocumented feature of this function is that, |
| 119 | +//! when given a `.bat` file as the application to run, it will automatically |
| 120 | +//! convert that into running `cmd.exe /c` with the bat file as the next argument. |
| 121 | +//! |
| 122 | +//! For historical reasons Rust currently preserves this behaviour when using |
| 123 | +//! [`Command::new`], and escapes the arguments according to `cmd.exe` rules. |
| 124 | +//! Due to the complexity of `cmd.exe` argument handling, it might not be |
| 125 | +//! possible to safely escape some special chars, and using them will result |
| 126 | +//! in an error being returned at process spawn. The set of unescapeable |
| 127 | +//! special chars might change between releases. |
| 128 | +//! |
| 129 | +//! Also note that running `.bat` scripts in this way may be removed in the |
| 130 | +//! future and so should not be relied upon. |
| 131 | +//! |
91 | 132 | //! [`spawn`]: Command::spawn
|
92 | 133 | //! [`output`]: Command::output
|
93 | 134 | //!
|
|
97 | 138 | //!
|
98 | 139 | //! [`Write`]: io::Write
|
99 | 140 | //! [`Read`]: io::Read
|
| 141 | +//! |
| 142 | +//! [`arg`]: Command::arg |
| 143 | +//! [`args`]: Command::args |
| 144 | +//! [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg |
| 145 | +//! |
| 146 | +//! [`CreateProcessW`]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw |
100 | 147 |
|
101 | 148 | #![stable(feature = "process", since = "1.0.0")]
|
102 | 149 | #![deny(unsafe_op_in_unsafe_fn)]
|
@@ -611,6 +658,22 @@ impl Command {
|
611 | 658 | /// escaped characters, word splitting, glob patterns, variable substitution, etc.
|
612 | 659 | /// have no effect.
|
613 | 660 | ///
|
| 661 | + /// <div class="warning"> |
| 662 | + /// |
| 663 | + /// On Windows use caution with untrusted inputs. Most applications use the |
| 664 | + /// standard convention for decoding arguments passed to them. These are safe to use with `arg`. |
| 665 | + /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments |
| 666 | + /// and are therefore vulnerable to malicious input. |
| 667 | + /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. |
| 668 | + /// |
| 669 | + /// See [Windows argument splitting][windows-args] for more details |
| 670 | + /// or [`raw_arg`] for manually implementing non-standard argument encoding. |
| 671 | + /// |
| 672 | + /// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg |
| 673 | + /// [windows-args]: crate::process#windows-argument-splitting |
| 674 | + /// |
| 675 | + /// </div> |
| 676 | + /// |
614 | 677 | /// # Examples
|
615 | 678 | ///
|
616 | 679 | /// Basic usage:
|
@@ -641,6 +704,22 @@ impl Command {
|
641 | 704 | /// escaped characters, word splitting, glob patterns, variable substitution, etc.
|
642 | 705 | /// have no effect.
|
643 | 706 | ///
|
| 707 | + /// <div class="warning"> |
| 708 | + /// |
| 709 | + /// On Windows use caution with untrusted inputs. Most applications use the |
| 710 | + /// standard convention for decoding arguments passed to them. These are safe to use with `args`. |
| 711 | + /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments |
| 712 | + /// and are therefore vulnerable to malicious input. |
| 713 | + /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. |
| 714 | + /// |
| 715 | + /// See [Windows argument splitting][windows-args] for more details |
| 716 | + /// or [`raw_arg`] for manually implementing non-standard argument encoding. |
| 717 | + /// |
| 718 | + /// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg |
| 719 | + /// [windows-args]: crate::process#windows-argument-splitting |
| 720 | + /// |
| 721 | + /// </div> |
| 722 | + /// |
644 | 723 | /// # Examples
|
645 | 724 | ///
|
646 | 725 | /// Basic usage:
|
|
0 commit comments