diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..048b1cf2c
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [blueimp]
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..0153ebdf5
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,80 @@
+name: Test
+
+on: [push, pull_request]
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [14, 16]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm install
+ - run: npm run lint
+
+ mocha:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files
+ - name: docker-compose build
+ run: docker-compose build example mocha
+ - name: mocha
+ run: docker-compose run --rm mocha
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+
+ wdio-chrome:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files wdio/reports
+ - name: docker-compose build
+ run: docker-compose build example
+ - name: wdio chrome
+ run: docker-compose run --rm wdio
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+ - name: Upload reports
+ if: always()
+ uses: actions/upload-artifact@v2
+ with:
+ name: reports
+ path: wdio/reports
+
+ wdio-firefox:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files wdio/reports
+ - name: docker-compose build
+ run: docker-compose build example
+ - name: wdio firefox
+ run: docker-compose run --rm wdio conf/firefox.js
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+ - name: Upload reports
+ if: always()
+ uses: actions/upload-artifact@v2
+ with:
+ name: reports
+ path: wdio/reports
diff --git a/.gitignore b/.gitignore
index 29a41a8c4..84901da00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-.DS_Store
*.pyc
+.env
node_modules
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 2326ad031..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Issue Guidelines
-
-The issues tracker should only be used for **bugs** or **feature requests**.
-
-Please post **support requests** and **general discussions** about this project to the [support forum](https://groups.google.com/d/forum/jquery-fileupload).
-
-## Bugs
-
-Please follow these guidelines before reporting a bug:
-
-1. **Update to the latest version** — Check if you can reproduce the issue with the latest version from the `master` branch.
-
-2. **Use the GitHub issue search** — check if the issue has already been reported. If it has been, please comment on the existing issue.
-
-3. **Isolate the demonstrable problem** — Try to reproduce the problem with the [Demo](http://blueimp.github.io/jQuery-File-Upload/) or with a reduced test case that includes the least amount of code necessary to reproduce the problem.
-
-4. **Provide a means to reproduce the problem** — Please provide as much details as possible, e.g. server information, browser and operating system versions, steps to reproduce the problem. If possible, provide a link to your reduced test case, e.g. via [JSFiddle](http://jsfiddle.net/).
-
-
-## Feature requests
-
-Please follow the bug guidelines above for feature requests, i.e. update to the latest version and search for exising issues before posting a new request.
-
-Generally, feature requests might be accepted if the implementation would benefit a broader use case or the project could be considered incomplete without that feature.
-
-If you need help integrating this project into another framework, please post your request to the [support forum](https://groups.google.com/d/forum/jquery-fileupload).
-
-## Pull requests
-
-[Pull requests](https://help.github.com/articles/using-pull-requests) are welcome and the preferred way of accepting code contributions.
-
-However, if you add a server-side upload handler implementation for another framework, please continue to maintain this version in your own fork without sending a pull request. You are welcome to add a link and possibly documentation about your implementation to the [Wiki](https://github.com/blueimp/jQuery-File-Upload/wiki).
-
-Please follow these guidelines before sending a pull request:
-
-1. Update your fork to the latest upstream version.
-
-2. Follow the coding conventions of the original repository. Changes to one of the JavaScript source files are required to pass the [JSLint](http://jslint.com/) validation tool.
-
-3. Keep your commits as atomar as possible, i.e. create a new commit for every single bug fix or feature added.
-
-4. Always add meaningfull commit messages.
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index 97303fc6c..000000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * jQuery File Upload Gruntfile
- * https://github.com/blueimp/jQuery-File-Upload
- *
- * Copyright 2013, Sebastian Tschan
- * https://blueimp.net
- *
- * Licensed under the MIT license:
- * http://www.opensource.org/licenses/MIT
- */
-
-/*global module */
-
-module.exports = function (grunt) {
- 'use strict';
-
- grunt.initConfig({
- jshint: {
- all: [
- 'Gruntfile.js',
- 'js/cors/*.js',
- 'js/*.js'
- ]
- }
- });
-
- grunt.loadNpmTasks('grunt-contrib-jshint');
- grunt.loadNpmTasks('grunt-bump-build-git');
- grunt.registerTask('default', ['jshint']);
-
-};
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..ca9e708c6
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,20 @@
+MIT License
+
+Copyright © 2010 Sebastian Tschan, https://blueimp.net
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index 726e6b342..9a093c6af 100644
--- a/README.md
+++ b/README.md
@@ -1,123 +1,224 @@
-# jQuery File Upload Plugin
-
-## Demo
-[Demo File Upload](http://blueimp.github.io/jQuery-File-Upload/)
+# jQuery File Upload
+
+## Contents
+
+- [Description](#description)
+- [Demo](#demo)
+- [Features](#features)
+- [Security](#security)
+- [Setup](#setup)
+- [Requirements](#requirements)
+ - [Mandatory requirements](#mandatory-requirements)
+ - [Optional requirements](#optional-requirements)
+ - [Cross-domain requirements](#cross-domain-requirements)
+- [Browsers](#browsers)
+ - [Desktop browsers](#desktop-browsers)
+ - [Mobile browsers](#mobile-browsers)
+ - [Extended browser support information](#extended-browser-support-information)
+- [Testing](#testing)
+- [Support](#support)
+- [License](#license)
## Description
-File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
-Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-## Setup
-* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
-* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
-
-## Support
+> File Upload widget with multiple file selection, drag&drop support, progress
+> bars, validation and preview images, audio and video for jQuery.
+> Supports cross-domain, chunked and resumable file uploads and client-side
+> image resizing.
+> Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
+> Node.js, Go etc.) that supports standard HTML form file uploads.
-* **[Support Forum](https://groups.google.com/d/forum/jquery-fileupload)**
-**Support requests** and **general discussions** about the File Upload plugin can be posted to the official
-[Support Forum](https://groups.google.com/d/forum/jquery-fileupload).
-If your question is not directly related to the File Upload plugin, you might have a better chance to get a reply by posting to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload).
+## Demo
-* Bugs and Feature requests
-**Bugs** and **Feature requests** can be reported using the [issues tracker](https://github.com/blueimp/jQuery-File-Upload/issues).
-Please read the [issue guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before posting.
+[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
## Features
-* **Multiple file upload:**
+
+- **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
-* **Drag & Drop support:**
- Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
-* **Upload progress bar:**
- Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
-* **Cancelable uploads:**
+- **Drag & Drop support:**
+ Allows to upload files by dragging them from your desktop or file manager and
+ dropping them on your browser window.
+- **Upload progress bar:**
+ Shows a progress bar indicating the upload progress for individual files and
+ for all uploads combined.
+- **Cancelable uploads:**
Individual file uploads can be canceled to stop the upload progress.
-* **Resumable uploads:**
+- **Resumable uploads:**
Aborted uploads can be resumed with browsers supporting the Blob API.
-* **Chunked uploads:**
- Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
-* **Client-side image resizing:**
- Images can be automatically resized on client-side with browsers supporting the required JS APIs.
-* **Preview images, audio and video:**
- A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs.
-* **No browser plugins (e.g. Adobe Flash) required:**
- The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
-* **Graceful fallback for legacy browsers:**
- Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
-* **HTML file upload form fallback:**
- Allows progressive enhancement by using a standard HTML file upload form as widget element.
-* **Cross-site file uploads:**
- Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects.
-* **Multiple plugin instances:**
+- **Chunked uploads:**
+ Large files can be uploaded in smaller chunks with browsers supporting the
+ Blob API.
+- **Client-side image resizing:**
+ Images can be automatically resized on client-side with browsers supporting
+ the required JS APIs.
+- **Preview images, audio and video:**
+ A preview of image, audio and video files can be displayed before uploading
+ with browsers supporting the required APIs.
+- **No browser plugins (e.g. Adobe Flash) required:**
+ The implementation is based on open standards like HTML5 and JavaScript and
+ requires no additional browser plugins.
+- **Graceful fallback for legacy browsers:**
+ Uploads files via XMLHttpRequests if supported and uses iframes as fallback
+ for legacy browsers.
+- **HTML file upload form fallback:**
+ Allows progressive enhancement by using a standard HTML file upload form as
+ widget element.
+- **Cross-site file uploads:**
+ Supports uploading files to a different domain with cross-site XMLHttpRequests
+ or iframe redirects.
+- **Multiple plugin instances:**
Allows to use multiple plugin instances on the same webpage.
-* **Customizable and extensible:**
- Provides an API to set individual options and define callBack methods for various upload events.
-* **Multipart and file contents stream uploads:**
- Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
-* **Compatible with any server-side application platform:**
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
+- **Customizable and extensible:**
+ Provides an API to set individual options and define callback methods for
+ various upload events.
+- **Multipart and file contents stream uploads:**
+ Files can be uploaded as standard "multipart/form-data" or file contents
+ stream (HTTP PUT file upload).
+- **Compatible with any server-side application platform:**
+ Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
+ Node.js, Go etc.) that supports standard HTML form file uploads.
-## Requirements
+## Security
-### Mandatory requirements
-* [jQuery](http://jquery.com/) v. 1.6+
-* [jQuery UI widget factory](http://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included)
-* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included)
+⚠️ Please read the [VULNERABILITIES](VULNERABILITIES.md) document for a list of
+fixed vulnerabilities
-The jQuery UI widget factory is a requirement for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite.
+Please also read the [SECURITY](SECURITY.md) document for instructions on how to
+securely configure your Web server for file uploads.
-The jQuery Iframe Transport is required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
+## Setup
-### Optional requirements
-* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.3+
-* [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.11.0+
-* [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.0+
-* [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.12.0+
-* [Bootstrap CSS framework](http://getbootstrap.com/) v. 3.0.0+
-* [Glyphicons](http://glyphicons.com/)
+jQuery File Upload can be installed via [NPM](https://www.npmjs.com/):
+
+```sh
+npm install blueimp-file-upload
+```
+
+This allows you to include [jquery.fileupload.js](js/jquery.fileupload.js) and
+its extensions via `node_modules`, e.g:
-The JavaScript Templates engine is used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
+```html
+
+```
-The JavaScript Load Image library and JavaScript Canvas to Blob polyfill are required for the image previews and resizing functionality.
+The widget can then be initialized on a file upload form the following way:
-The blueimp Gallery is used to display the uploaded images in a lightbox.
+```js
+$('#fileupload').fileupload();
+```
-The user interface of all versions except the jQuery UI version is built with Twitter's [Bootstrap](http://getbootstrap.com/) framework and icons from [Glyphicons](http://glyphicons.com/).
+For further information, please refer to the following guides:
+
+- [Main documentation page](https://github.com/blueimp/jQuery-File-Upload/wiki)
+- [List of all available Options](https://github.com/blueimp/jQuery-File-Upload/wiki/Options)
+- [The plugin API](https://github.com/blueimp/jQuery-File-Upload/wiki/API)
+- [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
+- [How to use only the basic plugin.](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
+
+## Requirements
+
+### Mandatory requirements
+
+- [jQuery](https://jquery.com/) v1.7+
+- [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v1.9+
+ (included): Required for the basic File Upload plugin, but very lightweight
+ without any other dependencies from the jQuery UI suite.
+- [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js)
+ (included): Required for
+ [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
+
+### Optional requirements
+
+- [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates)
+ v3+: Used to render the selected and uploaded files.
+- [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image)
+ v2+: Required for the image previews and resizing functionality.
+- [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob)
+ v3+:Required for the resizing functionality.
+- [blueimp Gallery](https://github.com/blueimp/Gallery) v2+: Used to display the
+ uploaded images in a lightbox.
+- [Bootstrap](https://getbootstrap.com/) v3+: Used for the demo design.
+- [Glyphicons](https://glyphicons.com/) Icon set used by Bootstrap.
### Cross-domain requirements
-[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server.
-The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests).
-The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](http://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service.
+[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads)
+using the
+[Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js)
+require a redirect back to the origin server to retrieve the upload results. The
+[example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js)
+makes use of
+[result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html)
+as a static redirect page for the origin server.
+
+The repository also includes the
+[jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js),
+which enables limited cross-domain AJAX requests in Microsoft Internet Explorer
+8 and 9 (IE 10 supports cross-domain XHR requests).
+The XDomainRequest object allows GET and POST requests only and doesn't support
+file uploads. It is used on the
+[Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files
+from the cross-domain demo file upload service.
## Browsers
### Desktop browsers
-The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions:
-* Google Chrome
-* Apple Safari 4.0+
-* Mozilla Firefox 3.0+
-* Opera 11.0+
-* Microsoft Internet Explorer 6.0+
+The File Upload plugin is regularly tested with the latest browser versions and
+supports the following minimal versions:
+
+- Google Chrome
+- Apple Safari 4.0+
+- Mozilla Firefox 3.0+
+- Opera 11.0+
+- Microsoft Internet Explorer 6.0+
### Mobile browsers
-The File Upload plugin has been tested with and supports the following mobile browsers:
-* Apple Safari on iOS 6.0+
-* Google Chrome on iOS 6.0+
-* Google Chrome on Android 4.0+
-* Default Browser on Android 2.3+
-* Opera Mobile 12.0+
+The File Upload plugin has been tested with and supports the following mobile
+browsers:
-### Supported features
-For a detailed overview of the features supported by each browser version please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
+- Apple Safari on iOS 6.0+
+- Google Chrome on iOS 6.0+
+- Google Chrome on Android 4.0+
+- Default Browser on Android 2.3+
+- Opera Mobile 12.0+
-## License
-Released under the [MIT license](http://www.opensource.org/licenses/MIT).
+### Extended browser support information
+
+For a detailed overview of the features supported by each browser version and
+known operating system / browser bugs, please have a look at the
+[Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
-## Donations
-jQuery File Upload is free software, but you can donate to support the developer, Sebastian Tschan:
+## Testing
-Flattr: [](https://flattr.com/thing/286433/jQuery-File-Upload-Plugin)
+The project comes with three sets of tests:
+
+1. Code linting using [ESLint](https://eslint.org/).
+2. Unit tests using [Mocha](https://mochajs.org/).
+3. End-to-end tests using [blueimp/wdio](https://github.com/blueimp/wdio).
+
+To run the tests, follow these steps:
+
+1. Start [Docker](https://docs.docker.com/).
+2. Install development dependencies:
+ ```sh
+ npm install
+ ```
+3. Run the tests:
+ ```sh
+ npm test
+ ```
+
+## Support
+
+This project is actively maintained, but there is no official support channel.
+If you have a question that another developer might help you with, please post
+to
+[Stack Overflow](https://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload)
+and tag your question with `blueimp jquery file upload`.
+
+## License
-PayPal: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PYWYSYP77KL54)
+Released under the [MIT license](https://opensource.org/licenses/MIT).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..433a6853c
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,227 @@
+# File Upload Security
+
+## Contents
+
+- [Introduction](#introduction)
+- [Purpose of this project](#purpose-of-this-project)
+- [Mitigations against file upload risks](#mitigations-against-file-upload-risks)
+ - [Prevent code execution on the server](#prevent-code-execution-on-the-server)
+ - [Prevent code execution in the browser](#prevent-code-execution-in-the-browser)
+ - [Prevent distribution of malware](#prevent-distribution-of-malware)
+- [Secure file upload serving configurations](#secure-file-upload-serving-configurations)
+ - [Apache config](#apache-config)
+ - [NGINX config](#nginx-config)
+- [Secure image processing configurations](#secure-image-processing-configurations)
+- [ImageMagick config](#imagemagick-config)
+
+## Introduction
+
+For an in-depth understanding of the potential security risks of providing file
+uploads and possible mitigations, please refer to the
+[OWASP - Unrestricted File Upload](https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload)
+documentation.
+
+To securely setup the project to serve uploaded files, please refer to the
+sample
+[Secure file upload serving configurations](#secure-file-upload-serving-configurations).
+
+To mitigate potential vulnerabilities in image processing libraries, please
+refer to the
+[Secure image processing configurations](#secure-image-processing-configurations).
+
+By default, all sample upload handlers allow only upload of image files, which
+mitigates some attack vectors, but should not be relied on as the only
+protection.
+
+Please also have a look at the
+[list of fixed vulnerabilities](VULNERABILITIES.md) in jQuery File Upload, which
+relates mostly to the sample server-side upload handlers and how they have been
+configured.
+
+## Purpose of this project
+
+Please note that this project is not a complete file management product, but
+foremost a client-side file upload library for [jQuery](https://jquery.com/).
+The server-side sample upload handlers are just examples to demonstrate the
+client-side file upload functionality.
+
+To make this very clear, there is **no user authentication** by default:
+
+- **everyone can upload files**
+- **everyone can delete uploaded files**
+
+In some cases this can be acceptable, but for most projects you will want to
+extend the sample upload handlers to integrate user authentication, or implement
+your own.
+
+It is also up to you to configure your web server to securely serve the uploaded
+files, e.g. using the
+[sample server configurations](#secure-file-upload-serving-configurations).
+
+## Mitigations against file upload risks
+
+### Prevent code execution on the server
+
+To prevent execution of scripts or binaries on server-side, the upload directory
+must be configured to not execute files in the upload directory (e.g.
+`server/php/files` as the default for the PHP upload handler) and only treat
+uploaded files as static content.
+
+The recommended way to do this is to configure the upload directory path to
+point outside of the web application root.
+Then the web server can be configured to serve files from the upload directory
+with their default static files handler only.
+
+Limiting file uploads to a whitelist of safe file types (e.g. image files) also
+mitigates this issue, but should not be the only protection.
+
+### Prevent code execution in the browser
+
+To prevent execution of scripts on client-side, the following headers must be
+sent when delivering generic uploaded files to the client:
+
+```
+Content-Type: application/octet-stream
+X-Content-Type-Options: nosniff
+```
+
+The `Content-Type: application/octet-stream` header instructs browsers to
+display a download dialog instead of parsing it and possibly executing script
+content e.g. in HTML files.
+
+The `X-Content-Type-Options: nosniff` header prevents browsers to try to detect
+the file mime type despite the given content-type header.
+
+For known safe files, the content-type header can be adjusted using a
+**whitelist**, e.g. sending `Content-Type: image/png` for PNG files.
+
+### Prevent distribution of malware
+
+To prevent attackers from uploading and distributing malware (e.g. computer
+viruses), it is recommended to limit file uploads only to a whitelist of safe
+file types.
+
+Please note that the detection of file types in the sample file upload handlers
+is based on the file extension and not the actual file content. This makes it
+still possible for attackers to upload malware by giving their files an image
+file extension, but should prevent automatic execution on client computers when
+opening those files.
+
+It does not protect at all from exploiting vulnerabilities in image display
+programs, nor from users renaming file extensions to inadvertently execute the
+contained malicious code.
+
+## Secure file upload serving configurations
+
+The following configurations serve uploaded files as static files with the
+proper headers as
+[mitigation against file upload risks](#mitigations-against-file-upload-risks).
+Please do not simply copy&paste these configurations, but make sure you
+understand what they are doing and that you have implemented them correctly.
+
+> Always test your own setup and make sure that it is secure!
+
+e.g. try uploading PHP scripts (as "example.php", "example.php.png" and
+"example.png") to see if they get executed by your web server, e.g. the content
+of the following sample:
+
+```php
+GIF89ad
+ # Some of the directives require the Apache Headers module. If it is not
+ # already enabled, please execute the following command and reload Apache:
+ # sudo a2enmod headers
+ #
+ # Please note that the order of directives across configuration files matters,
+ # see also:
+ # https://httpd.apache.org/docs/current/sections.html#merging
+
+ # The following directive matches all files and forces them to be handled as
+ # static content, which prevents the server from parsing and executing files
+ # that are associated with a dynamic runtime, e.g. PHP files.
+ # It also forces their Content-Type header to "application/octet-stream" and
+ # adds a "Content-Disposition: attachment" header to force a download dialog,
+ # which prevents browsers from interpreting files in the context of the
+ # web server, e.g. HTML files containing JavaScript.
+ # Lastly it also prevents browsers from MIME-sniffing the Content-Type,
+ # preventing them from interpreting a file as a different Content-Type than
+ # the one sent by the webserver.
+
--File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.
-
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
--File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
-
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
--File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
-
- Supports cross-domain, chunked and resumable file uploads.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.