Request to non-existing route can attempt to write on disk


Recently we’ve had some bot activity on our production app. One request was sent to /admin/Upload, which is a path that does not exist in our application. In such cases, it’s expected to halt and return 404 - Not Found (as it usually does). However, the request failed because it couldn’t create a temporary directory due to missing write permission (rightfully so). Here’s the error:

Request: POST /admin/Upload
    ** (exit) an exception was raised:
    ** (Plug.UploadError) could not create a tmp directory to store uploads. Set PLUG_TMPDIR to a directory with write permission
    (plug 1.14.2) lib/plug/upload.ex:185: Plug.Upload.random_file!/1
    (plug 1.14.2) lib/plug/parsers/multipart.ex:295: Plug.Parsers.MULTIPART. handle_disposition/3
    (plug 1.14.2) lib/plug/parsers/multipart.ex:200: Plug.Parsers.MULTIPART.parse_multipart_headers/5
    (plug 1.14.2) lib/plug/parsers/multipart.ex:186: Plug.Parsers.MULTIPART.parse_multipart/5
    (plug 1.14.2) lib/plug/parsers/multipart.ex:175: Plug.Parsers.MULTIPART.parse_multipart/2
    (plug 1.14.2) lib/plug/parsers/multipart.ex:127: Plug.Parsers.MULTIPART.parse/5
    (plug 1.14.2) lib/plug/parsers.ex:340: Plug.Parsers.reduce/8
    (danko_web 0.1.0) lib/danko_web/endpoint.ex:1: DankoWeb.Endpoint.plug_builder_call/2

Why did the request get processed so far instead of dying early?

Thank you!

The overall answer here is relatively simple. If you look at your endpoint.ex module you’ll see a bunch of plug invocations. These define the plug pipeline that hands requests that come in, and the plugs are executed in the sequence in which they are shown in the module. plug Plug.Parsers is pretty high up in the chain, and your router is pretty far down (generally the bottom). When Plug.Parsers handles a request that is multipart it writes the file contents to a temporary file.

If you have no plans to support file uploading at all I would simply remove :multipart from the list of accepted types on that plug.


Ah I see, that makes sense. I didn’t even think about this since I assumed router as the entry point. Thank you!