Running another program has two shapes. You can hand over a command and a list of arguments, or you can hand over one string and let something split it into a command and a list of arguments. The second shape has a step in it that the first does not, and that step is where the defect lives.
Note what is not required here: no semicolon, no backtick, no shell metacharacter at all. A value containing a space becomes two arguments. A value beginning with a dash becomes a flag the program obeys.
GET /documents/d1/thumbnail?size=200x200An ordinary call. Look at the argument vector each build assembled.
GET /documents/d1/thumbnail?size=200x200%20-write%20%2Fetc%2FpasswdOne value with a space in it. Count the arguments in each transcript.