CVE-2024-24576 is a recently published vulnerability in the Rust stdlib. The short version is that passing arguments to .bat
files on Windows via Command::new("./test.bat").arg(untrusted_string)
is actually unsafe in Rust despite the fact that the .arg
/.args
functions are supposed to do essentially the same thing as passing argv
to execve()
(so no shell interpolation/escaping shenanigans like with system()
).
Quoting from Rust docs:
Note that the argument is not passed through a shell, but given literally to the program. This means that shell syntax like quotes, escaped characters, word splitting, glob patterns, variable substitution, etc. have no effect.
Despite the original CVE talking about Rust, there is a BatBadBut
blog post and a vulnerability note VU#123335 claiming that other languages are also affected (including Python). And that, in the case of Python, there would be a documentation update regarding this vulnerability.
The python version of the POC would be something like this.
test.py
:
import subprocess
untrusted_string = 'foo" & whoami'
subprocess.run(["test.bat", untrusted_string])
test.bat
:
@echo off
echo Argument passed: %1
Note that shell=True
is NOT used here, and the âequivalentâ POSIX/Unix/Linux code with ./test.sh
containing echo $1
does not appear to be vulnerable (as expected).
So Python is indeed affected by this vulnerability?
I find the current behaviour to be extremely surprising (although I understand that realistically Windows is at fault here, not Python). The current documentation even has a couple sections talking about shell=True
vs shell=False
and argument sequences on Windows that seem to imply that python does try to escape the supplied arguments when shell=False
. A user that is not familiar with how cmd.exe
is used on Windows when executing .bat
files might reasonably assume that the above POC is safe (as it is safe on Linux).
Was this issue discussed anywhere (I wasnât able to find anything on the CPython github)? What documentation change is the blogpost talking about?
The Rust stdlib is going to âfixâ this issue by refusing to run batch files on Windows with arguments that contain quotation marks by default. Should Python consider doing the same?