At Uploadcare, we always take security seriously, and that’s why we try to avoid even hypothetical security problems. That’s the reason behind this latest decision.
As a service provider for handling user-generated content, we need to keep the data from your users in its original state unless you request any changes. That’s why Uploadcare’s URL API for content processing not only allows you to apply an unlimited number of transformations, but also query the original file anytime by simply removing all URL API operations.
The content itself, however, tells nothing about what to do with it — it’s just a stream of bytes. That’s why each uploaded file has a Content-Type HTTP header associated with it. Browsers and other clients can distinguish different file types by the so-called MIME type (which is a part of the Content-Type header). For example, if the MIME is
text/plain, then the file should be shown as a text without any formatting. If the MIME is
image/jpeg, then the file is probably a valid JPEG image.
HTTP headers for a typical JPEG file.
The problem comes when a file uploaded by a user has a
text/html MIME type. Basically, this means that the file is an HTML page and can execute scripts. This reveals a bunch of attack vectors including phishing and XSS.
Fortunately, another header comes to the rescue.
Content-Disposition allows choosing what to do with the content. When the value of the header is
Content-Disposition: inline, the browser must try to process the content (e.g., show images and web pages, open PDF files). When the value is
Content-Disposition: attachment, the browser must not process content, but save it locally instead.
Every time a user uploads a file, Uploadcare inspects it and determines its format. If the system comes to the conclusion that the file is an image, you’ll be able to process the file as an image, for example, by applying transformations: resize, enhance, flip, etc. Also, by default,
Content-Disposition is set to
inline if the file is an image.
And this is where the problem arises. If an intruder uploads a specially crafted file that could be decoded as an image (JPEG, for example) but with a MIME type of
text/html MIME type. But, after having a better look at how our customers work with files, we came to the conclusion that it would only delay the problem and eventually make it even worse.
Bare file URLs (without any operations applied) are quite common for our customers’ applications, since it’s a simple way to show uploaded files to the end user. So, if we made all bare URLs into attachments, customers would have to search for another way to show files, and chances are it would be to force
inline regardless of file content using the inline operation. Not only would it not solve the vulnerability issue, but it would also lead to extra work for Uploadcare clients. This is quite the opposite of what we wanted to achieve.
Instead, we picked several safe types that most browsers could display natively and made them inlinable. Those types include:
video/*. All other MIME types are
attachments by default.
Usually, we try to make all changes to our URL API backward compatible. This case is a noticeable exception, since we believe the influence on existing applications is moderate while the benefits for further applications are significant.
However, please check your application and consider adding the
-/inline/no/ operation if you relied on the old behavior where all files except images are attachments.
All these changes are only related to the default behavior for bare file URLs, where no inline operation is applied. If the inline operation is applied, the behavior is unchanged.