multer icon indicating copy to clipboard operation
multer copied to clipboard

File size limit cancels file upload only after all bytes are received

Open csaroff opened this issue 8 years ago • 33 comments

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?

csaroff avatar May 09 '16 19:05 csaroff

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 avatar Jun 12 '16 08:06 Sylcan

@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?

csaroff avatar Jun 16 '16 19:06 csaroff

@LinusU has this been fixed?

goatandsheep avatar Sep 16 '16 16:09 goatandsheep

This needs a fix, I'll see if I can PR.

DiegoRBaquero avatar Jan 19 '17 16:01 DiegoRBaquero

PR sent: https://github.com/expressjs/multer/pull/447

DiegoRBaquero avatar Jan 19 '17 20:01 DiegoRBaquero

Any news ?

shiro-42 avatar Mar 24 '17 10:03 shiro-42

+1

ericzon avatar Apr 19 '17 14:04 ericzon

any updates ?

SachinKalsi avatar Jul 04 '17 17:07 SachinKalsi

+1

mbiakov avatar Jun 28 '18 08:06 mbiakov

+1

ziogibom avatar Jul 05 '18 06:07 ziogibom

@csaroff This refers to the same issue https://github.com/expressjs/multer/issues/525

HarshithaKP avatar Oct 09 '19 10:10 HarshithaKP

Labeling and self assigning to look at this later

jonchurch avatar Jan 18 '20 22:01 jonchurch

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.

Rc85 avatar Mar 04 '20 15:03 Rc85

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!

LinusU avatar Mar 09 '20 11:03 LinusU

I think this needs a reproduction if someone has the time

jonchurch avatar Mar 10 '20 12:03 jonchurch

@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.

csaroff avatar Mar 10 '20 15:03 csaroff

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?

LinusU avatar Mar 10 '20 15:03 LinusU

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 😄

csaroff avatar Mar 11 '20 04:03 csaroff

Is there any update in regards to this issue? Does this really persist since 2016?

linus-hologram avatar Apr 13 '20 17:04 linus-hologram

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

gbkwiatt avatar Jul 23 '20 13:07 gbkwiatt

Regarding file size limit, I produced a solution in https://github.com/expressjs/multer/issues/820

Antonius-S avatar Oct 27 '20 13:10 Antonius-S

The issue still persists, has anyone found any work around ?

satcasm avatar Jan 08 '21 13:01 satcasm

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...

LinusU avatar Jan 12 '21 17:01 LinusU

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 avatar Oct 09 '22 09:10 kazeens

@kazeens have you seen my questions in this thread asking for clarifications? Unless someone answers me, I cannot really do anything here 🤷‍♂️

LinusU avatar Oct 11 '22 08:10 LinusU

@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 avatar Oct 11 '22 08:10 csaroff

@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...

LinusU avatar Oct 11 '22 09:10 LinusU

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:

  1. Waiting until all bytes have been sent by the browser before returning 413
  2. 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

csaroff avatar Oct 11 '22 20:10 csaroff