The PHP function escapeshellarg()
turns this:
"A schema"."A table"
Into this:
" A schema . A table "
That is, it replaces the quotes with spaces instead of quoting them. The expected and desired result (by me) is:
"\"A schema\".\"A table\""
This has wasted countless hours of my life troubleshooting. For the longest time, I just couldn't figure out what was happening; it never occured to my brain that it could be so stupid as to actually remove the double quotes entirely! Even if this "makes it safe", it's such a bizarre thing to do when escaping them would not only be the standard and supported way of handling this, but would result in no problems arising from using this function.
It should be noted that I've read the comments on: https://www.php.net/escapeshellarg
I have also read a lot of other texts complaining about this function and about Windows shell escaping and whatnot, so I'm at least "vaguely" aware of the reason: "It's complicated."
However, I find myself utterly crippled by this core function (escapeshellarg
), as sadly so often is the case with PHP, and I find myself trying to make my own function to replace it. This, of course, is extremely problematic and scary since half the point of this function is security-related! It's supposed to "make safe" an arbitrary string to be used as an argument on the command line, without risking that an attacker can "break out" from it and execute arbitrary commands!
For this reason, I'm pretty sure that simply doing:
$likely_not_a_safe_argument = '\"' . str_replace('"', '\"', $user_input) . '\"';
... is NOT safe! If it were that simple, then I'm certain that the PHP developers would do that for Windows inside escapeshellarg
.
Basically, I have no idea what to do now. And yes, I do need to send double quotes in arguments. Here is a real-world example of where it's necessary:
pg_dump --format plain --verbose --file "dump.txt" --exclude-table-data="\"Test schema\".\"Test table\"" --host="localhost" --port="5432" --username="postgres" --dbname="testdb"
(No, it doesn't take single quotes or anything else. It must be double quotes around the identifiers.)
How should I safely "improve" escapeshellarg() so that it doesn't nuke my double quotes? What does everyone else do?