Securing File Uploads with JavaScript

Securing File Uploads with JavaScript

Introduction

File uploads are a common feature in web applications, allowing users to upload documents, images, and other types of files to be stored and shared on a server. However, they can also pose a significant security risk if not implemented correctly.

Attackers can use file uploads to inject malicious code into your application, steal sensitive data, or even take control of your server. As such, securing file uploads is a critical aspect of web application security.

In this article, we will discuss some best practices for securing file uploads with JavaScript. We would also see how we can use the popular file-handling library Filestack to handle some of these security concerns.

Best Practices For Securing File Uploads With JavaScript

Validating File types and size

One of the most important steps in securing file uploads is to validate the file type before accepting it. This ensures that the uploaded file is of the expected type and size and restricts file types to those that are safe and necessary for your application.

This can be done by checking the file extension or by using a library that can identify the file type based on its contents. It is also important to specify the maximum size limit for uploaded files to prevent large files from causing denial-of-service attacks or other security issues.

Use server-side validation

Client-side validation can be easily bypassed, making it crucial to use server-side validation to verify that the file is safe and does not contain malicious code. Server-side validation is more reliable and can detect any issues that might have been missed during client-side validation.

Use SSL/TLS encryption

Use SSL/TLS encryption to secure the connection between the client and server. This prevents attackers from intercepting and modifying the uploaded file. Encryption also ensures that the data transmitted between the client and server is confidential.

Sanitize file names

Sanitizing file names involves removing any special characters or symbols that could be used to exploit vulnerabilities in your application. Attackers can exploit vulnerabilities in file upload mechanisms to upload files that contain malicious code, such as JavaScript or PHP code, which can then be executed on the server. Sanitizing file names helps prevent attackers from injecting malicious code into your application via file names.

Store files outside of the web root

Storing uploaded files outside of the web root directory is crucial to prevent them from being accessed directly by users or attackers. This ensures that uploaded files can only be accessed through the web application and not directly from the file system.

Implement access controls

Implement access controls to restrict who can upload files and who can access them. Use authentication and authorization mechanisms to ensure that only authorized users can upload and access files. This helps prevent unauthorized access and ensures that the data remains confidential.

Scan uploaded files for malware

Scanning uploaded files for malware is essential to detect and remove any malicious files that may have been uploaded. This can be done using antivirus software or other security tools.

Limit file upload size

Limiting the size of uploaded files is essential to prevent denial-of-service attacks or other security issues that may arise from large files. Specify a maximum file size limit that is reasonable for your application and set an appropriate limit for your application.

Use a content delivery network (CDN)

Using a CDN to store and distribute files can improve performance and reduce the load on your server. CDNs also provide additional security measures such as DDoS protection and SSL/TLS encryption, making them an excellent option for securing file uploads.

Using Filestack to Secure File Uploads

Handling all of these best practices for securing file uploads can seem to be a herculean task. I also feel that way at times when building web applications. Personally, I do not re-invent the wheel and I look out for third-party libraries that can help speed up development and provide robust features. I have found Filestack to be a good library for handling file uploads and delivery.

What is Filestack?

Filestack is a robust set of tools and powerful APIs that allow developers to upload, transform and deliver content easily.

Filestack enables developers to easily integrate file-handling capabilities into their applications. Developers can upload and store large files, transform and manipulate images and other file types, and deliver that content with blazing speed, responsively, across any type of desktop or mobile device.

Filestack leverages a CDN (Content Delivery Network) to ensure fast and reliable global access to assets. The CDN is used to access all files that are managed by the developer’s Filestack application.

Creating a developer account on Filestack is free. This can be done on their website. Upon signing up, you are provided with an API key that can be used to access Filestack’s features. Filestack has a Javascript SDK that can be imported via CDN or installed using a package manager.

Validating File Types and Sizes using Filestack

Filestack provides a beautiful File Picker UI that improves upon the default HTML image element. This UI provides support for drag-and-drop file uploads, uploads from other sources apart from your computer, and also basic image editing features like cropping and rotating.

Filestack allows us to provide an options object to the default File Picker which can be used to select a file and get information about that file, including the file type and size.

Here is an example of how to use Filestack to validate file types:

const client = filestack.init("YOUR_API_KEY");

const options = {
  // types of files that the user is allowed to choose
  accept: ["image/*", "application/pdf"],

  // Check the file type and size and throw error in this function to reject the file selection.
  // The error message will be displayed to the user as an alert.
  onFileSelected: function (file) {
    if (file.mimetype !== "application/pdf") {
      throw new Error("Only PDF files are allowed.");
    }

    if (file.size > 1000 * 1000) {
      throw new Error("File too big, select something smaller than 1MB");
    }
  },

  onUploadDone: (res) => console.log(res),
};

client.picker(options).open();

In this example, we use the Filestack library to pick a file and get information about it. We then check the file type and prevent the file from being uploaded if it is not a PDF file.

Secure Uploads with Filestack

Filestack provides built-in security features that can prevent malicious code injection. Filestack, by default, requires that requests that modify existing files or account settings are authenticated. Filestack also provides security settings in the developer portal that allows for every request including uploading or delivering files to be authenticated.

Filestack uses Base64URL-encoded JSON “policies” and HMAC-SHA256 “signatures” to provide authentication and authorization for its APIs. The policy determines which actions are authorized and the signature authenticates the policy.

A policy can be used to limit the types of requests allowed. The policy is an object that contains an expiry time in the Unix timestamp.

{
  "expiry": 1523595600,
  "call": ["pick","store","runWorkflows"],
}

// pick -    Ability to open Picker and pick files.
// store - Ability to store files in your storage destination.
// runWorkflows -    Ability to run workflows after the file is uploaded

Here is an example of how to use the policy and signature in the Picker Client:

const clientOptions = {
    security: {
        policy: "eyJleHBpcnkiOiAxNTQ2ODk5NDI4LCAiY2FsbCI6IFsicmVhZCIsICJzdGF0IiwgImNvbnZlcnQiLCAicGljayIsICJzdG9yZSJdfQ==",
        signature: "1fed86599156df046f925e0f773866654a4fc209b0b85b173b5d8088e898b685"
    }
}

const client = filestack.init(YOUR_API_KEY, clientOptions)
client.picker().open();

Conclusion

Securing file uploads is crucial for the security of your web application. By following the best practices outlined above, you can ensure that your file upload feature is secure and protects the sensitive data of your users.

Remember to validate file types and sizes, use server-side validation, encrypt your connection, sanitize file names, store files outside of the web root, implement access controls, scan uploaded files for malware, limit file upload size, and use a content delivery network (CDN).

You can also make use of third-party libraries like Filestack that make handling files easier and more secure.