I'd like users to be able to upload images from the web by providing a URL. I don't think I can get the client to fetch the image and upload it due to possible CORS issues and hotlink prevention, so I'm getting the server to do it.
The biggest concern is the user simply entering file:///home/user/secret_image.jpg
. This URL gets sent to the server and django happily fetches it, a local server side file, hosting it for the world to see. Is there a way to limit requests to external resources? How can this approach be made safe (at least -ish)?
Some other concerns may be the user providing a hostname that resolves to a local address or providing a public URL redirect to a local address. Even other devices on the LAN which wouldn't normally be accessible.
Filtering the URL text is not an option. I could perhaps check that the IP gets routed to a gateway and the destination is outside my subnet before allowing urllib to continue. I could block any redirects, but this may be a useful feature in some cases, so I could write a redirect handler to re-check the IP. Now this is starting to feel like a patch job and not a nice robust takes-care-of-all-cases solution.
I'm also doing basic stuff like read(max_size)
in case the file is huuge, using python-magic to check the mimetype and pick an extension, using django-ratelimit
and setting a timeout on the call to urlopen()
.
EDIT: related answer