multer
multer copied to clipboard
File size limit cancels file upload only after all bytes are received
I've been using multer for file uploads, and I've noticed an issue with the file size limit. I'm using the limits option to prevent the upload of files that are too large.
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fieldNameSize: 255,
fileSize: 500000,
files: 1,
fields: 1
}
});
When uploading an image to my API, multer seems to wait until it has received all of the image bytes before failing with the "LIMIT_FILE_SIZE" code.
Isn't it a security vulnerability if your API allows someone to upload an arbitrarily large file before failing the request? Is there another technique for preventing the behavior?
I'm having the same issue. I'd like to check the size before uploading.
Did you find something about this @csaroff ?
Thanks mate!
@Sylcan I haven't investigated this further, but this seems like a pretty serious issue. Checking the content length header really doesn't solve this issue for the exact reason that you stated. The content-length header is supplied by the api consumer.
@LinusU Do you have any insight here?
@LinusU has this been fixed?
This needs a fix, I'll see if I can PR.
PR sent: https://github.com/expressjs/multer/pull/447
Any news ?
+1
any updates ?
+1
+1
@csaroff This refers to the same issue https://github.com/expressjs/multer/issues/525
Labeling and self assigning to look at this later
A work around would be to include the filesize in the request headers. Otherwise, I don't think there is a way to check the filesize before uploading. There are no possible ways (that I can think of) to determine the filesize other than data in the file object being sent from the client.
When uploading an image to my API, multer seems to wait until it has received all of the image bytes before failing with the "LIMIT_FILE_SIZE" code.
@csaroff would you mind elaborating on this part a bit?
Are you seeing that memory usage is growing to the size of the entire file that is being uploaded, even though there is a file size limit in place?
Unless that is the case, I'm not really sure what the problem is? 🤔 Would love some more information!
I think this needs a reproduction if someone has the time
@LinusU 🎯
Yep, that's what I'm saying. Ideally, multer will end the http request(responding with a 413) when it has received more than limits.fileSize
bytes. Instead, it waits to receive all bytes before failing the request. It has been quite a while since I've used multer though and I'm not sure if the issue still exists.
Yep, that's what I'm saying.
Just to be super clear, are you saying that if you set file limit to 1MB, and upload a file that is 700MB, the memory usage of Node.js grows to over 700MB? That is, the entire file is stored in memory before returning the error?
It's been some time, but IIRC that's the behavior. It's probably worthwhile to note that I was using the in-memory adapter. storage: multer.memoryStorage()
. A small reproduction would probably yield more information though 😄
Is there any update in regards to this issue? Does this really persist since 2016?
Looks like, just had same issue, it uploads file first to memory somewhere, then checks size. not good if someone tries to upload 1GB file when 5MB is allowed
Regarding file size limit, I produced a solution in https://github.com/expressjs/multer/issues/820
The issue still persists, has anyone found any work around ?
Can someone please confirm that this is the behaviour seen:
Just to be super clear, are you saying that if you set file limit to 1MB, and upload a file that is 700MB, the memory usage of Node.js grows to over 700MB? That is, the entire file is stored in memory before returning the error?
If that is the case, then that is indeed an error. But if the problem is that the entire file is sent over the socket from the client to the server, I don't think that we can do anything about it. As far as I know, there is no way to tell the client to abort their upload and just accept the servers answer directly instead...
Is there any updates on that issue? Will there be implemented a flow where it preventively stops file upload once the indicated in limit property size value reached?
This still seems to be a huge security vulnerability
@kazeens have you seen my questions in this thread asking for clarifications? Unless someone answers me, I cannot really do anything here 🤷♂️
@LinusU What did you mean by "there is no way to tell the client to abort their upload and just accept the servers answer directly instead..."
I'm not sure what api multer has to work with, but as you receive each unit of data from the socket, can you count the number of bytes and keep a running total?
I think @Antonius-S posted a potential solution
https://github.com/expressjs/multer/issues/820#issuecomment-717233421
@csaroff is this the behaviour you are seeing? 👇
Just to be super clear, are you saying that if you set file limit to 1MB, and upload a file that is 700MB, the memory usage of Node.js grows to over 700MB? That is, the entire file is stored in memory before returning the error?
Because as far as I know, our implementation will simply throw away the bytes for each unit of data from the socket once the limit has been reached. If this is not the case, we should make it so.
What I don't believe that we can fix because of how browsers work today, would be that the client will still send all 700MB to the server. There simply isn't a way in HTTP/1.1 to tell the client to stop sending any more bytes, as far as I know...
Because as far as I know, our implementation will simply throw away the bytes for each unit of data from the socket once the limit has been reached. If this is not the case, we should make it so.
Gotcha. It's been more than 6 years, but IIRC that's the behavior. It's probably worthwhile to note that I was using the in-memory adapter. storage: multer.memoryStorage(). Probably needs to be reproduced though.
What I don't believe that we can fix because of how browsers work today, would be that the client will still send all 700MB to the server. There simply isn't a way in HTTP/1.1 to tell the client to stop sending any more bytes, as far as I know...
So it sounds like you can send back a 413 response early and close the connection, but most browsers will show a "connection reset" error.
https://stackoverflow.com/a/18370751/6051733
The heroic thing to do here would be to supply an option in multer to support:
- Waiting until all bytes have been sent by the browser before returning 413
- Returning 413 as soon as bytes exceed the limit.
Once all major browsers support (2), you could change the default. Idk if its worthwhile, just an idea
Is there any update to fix this vulnerability in next versions?
https://ossindex.sonatype.org/vulnerability/sonatype-2016-0121?component-type=npm&component-name=multer&utm_source=dependency-track&utm_medium=integration&utm_content=v4.4.2](url)
I'm not sure what information is missing here. What multer
should do is:
- Keep a running tally of the data received for a given file.
- If the bytes received over the readable stream exceed the configured limit, send a 413 response and close the stream. This is how HTTP handles this situation: you close the underlying TCP socket, and it no longer matters what the other side does. Because TCP is a duplex protocol, you do not need to wait until the other side stops to send your response.
- Discard the cached file automatically.
Is this not what multer
does already? That's what the documentation indicates, but all of these 413-related issues certainly make it seem like it's not working today.