Affects: 5.3.21


When a multipart request contains a part with a quote or backslash in the name or filename, it should be escaped. ContentDisposition properly escapes them when building the header, but it does not unescape them when parsing it. See the following code:

ContentDisposition cd = ContentDisposition.builder("form-data").name("file").filename("a\\nice \"file\" with \\\" quotes.txt").build();
System.out.println("Generated header: " + cd);
System.out.println("Original: " + cd.getFilename());
ContentDisposition parsed = ContentDisposition.parse(cd.toString());
System.out.println("Parsed:   " + parsed.getFilename());

output:

Generated header: form-data; name="file"; filename="a\nice \"file\" with \" quotes.txt"
Original: a\nice "file" with \" quotes.txt
Parsed:   a\nice \"file\" with \" quotes.txt

(also note that the last quote seems to be considered as already escaped so it does not get escaped – seems intentional from the original implementation in 956ffe68587c8d5f21135b5ce4650af0c2dea933)

The issue seems to come from ContentDisposition.java#L354-L356, which simply removes the outer quotes without unescaping:

String value = (part.startsWith("\"", eqIndex + 1) && part.endsWith("\"") ?
        part.substring(eqIndex + 2, part.length() - 1) :
        part.substring(eqIndex + 1));

We noticed this issue because we were seeing \" from MultipartFile.getOriginalFilename(), whereas Servlet’s Part.getSubmittedFileName() returns the correct value.

Comment From: poutsma

Fixing this will be a breaking change, so setting for 6.0.