I'm building a very simple endpoint to change a user's profile photo and can't find detailed information on how to verify an uploaded file is a real image. On the server, I can easily filter out requests to my endpoint based on the Content-Type
header; if the header is not one of the types I'm enforcing, then return a 400. Consider that I only want to receive images that are png, jpg or jpeg; my endpoint would have a condition as shown below:
const validImageMimeTypes = ['image/jpeg', 'image/jpg', 'image/png']
router.put('/:id/avatar', (req, res) => {
if (!validImageMimeTypes.includes(req.get('content-type'))) {
res.status(400)
res.send("Unsupported file type")
return
}
...
}
This is great, but it doesn't prevent an user from changing the extension of a file to one of the enforced ones and uploading it. I tried doing exactly this with my Github avatar picture, and their server-side was able to pick up on the fact that what I uploaded wasn't a real image:
{"message":"Expected formats \"png,jpg,gif\", got \"unknown\"",
"request_id":"F5F0:365D:1EC5D9:226D70:5C94E2AB",
"errors":[{"resource":"upload","code":"content_mismatch","field":"format"}]}
In general terms, how did they implement this validation? Are they using a library to obtain simple attributes from the image such as size and width, and if that fails return a 400? Any industry practices I should be aware of?
Thanks