VYPR
Critical severityOSV Advisory· Published Jan 2, 2026· Updated Apr 15, 2026

CVE-2026-21440

CVE-2026-21440

Description

AdonisJS is a TypeScript-first web framework. A Path Traversal vulnerability in AdonisJS multipart file handling may allow a remote attacker to write arbitrary files to arbitrary locations on the server filesystem. This impacts @adonisjs/bodyparser through version 10.1.1 and 11.x prerelease versions prior to 11.0.0-next.6. This issue has been patched in @adonisjs/bodyparser versions 10.1.2 and 11.0.0-next.6.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@adonisjs/bodyparsernpm
< 10.1.210.1.2
@adonisjs/bodyparsernpm
>= 11.0.0-next.0, < 11.0.0-next.611.0.0-next.6

Affected products

1

Patches

2
6795c0e3fa82

fix: path traversal during file.move operation

https://github.com/adonisjs/bodyparserHarminder VirkJan 2, 2026via ghsa
2 files changed · +13 5
  • src/multipart/file.ts+5 1 modified
    @@ -8,6 +8,7 @@
      */
     
     import { join } from 'node:path'
    +import crypto from 'node:crypto'
     import { Exception } from '@poppinss/utils'
     import Macroable from '@poppinss/macroable'
     
    @@ -181,7 +182,10 @@ export class MultipartFile extends Macroable {
           })
         }
     
    -    options = Object.assign({ name: this.clientName, overwrite: true }, options)
    +    options = Object.assign(
    +      { name: `${crypto.randomUUID()}.${this.extname ?? 'unknown'}`, overwrite: true },
    +      options
    +    )
         const filePath = join(location, options.name!)
     
         try {
    
  • tests/body_parser.spec.ts+8 4 modified
    @@ -24,7 +24,7 @@ import {
     import { AppFactory } from '@adonisjs/application/factories'
     
     import { Multipart } from '../src/multipart/main.js'
    -import { MultipartFile } from '../src/multipart/file.js'
    +import { type MultipartFile } from '../src/multipart/file.js'
     import { BodyParserMiddlewareFactory } from '../factories/middleware_factory.js'
     import { packageFilePath, packageFileSize, unicornFilePath } from '../tests_helpers/main.js'
     
    @@ -998,6 +998,7 @@ test.group('BodyParser Middleware | multipart', () => {
               await pkgFile.move(fs.basePath)
               assert.equal(pkgFile.state, 'moved')
               res.writeHead(200, { 'content-type': 'application/json' })
    +          res.write(JSON.stringify({ file: pkgFile }))
               res.end()
             } catch (error) {
               res.writeHead(500, { 'content-type': 'application/json' })
    @@ -1006,9 +1007,12 @@ test.group('BodyParser Middleware | multipart', () => {
           })
         })
     
    -    await supertest(server).post('/').attach('package', packageFilePath).expect(200)
    +    const { body } = await supertest(server)
    +      .post('/')
    +      .attach('package', packageFilePath)
    +      .expect(200)
     
    -    const uploadedFileContents = await fs.contents('package.json')
    +    const uploadedFileContents = await fs.contents(body.file.fileName)
         const originalFileContents = await readFile(packageFilePath, 'utf-8')
         assert.equal(uploadedFileContents, originalFileContents)
       })
    @@ -1055,7 +1059,7 @@ test.group('BodyParser Middleware | multipart', () => {
             const pkgFile = ctx.request.file('package')!
     
             try {
    -          await pkgFile.move(fs.basePath, { overwrite: false })
    +          await pkgFile.move(fs.basePath, { name: 'package.json', overwrite: false })
             } catch (error) {
               assert.equal(
                 error.message,
    
143a16f35602

fix: always generate a random filename when performing move operation

https://github.com/adonisjs/bodyparserHarminder VirkJan 2, 2026via ghsa
3 files changed · +14 5
  • src/bodyparser_middleware.ts+2 1 modified
    @@ -8,6 +8,7 @@
      */
     
     import { tmpdir } from 'node:os'
    +import string from '@poppinss/utils/string'
     import { join, isAbsolute } from 'node:path'
     import { Exception } from '@poppinss/utils/exception'
     import type { HttpContext } from '@adonisjs/http-server'
    @@ -110,7 +111,7 @@ export class BodyParserMiddleware {
           return isAbsolute(tmpPath) ? tmpPath : join(tmpdir(), tmpPath)
         }
     
    -    return join(tmpdir(), crypto.randomUUID())
    +    return join(tmpdir(), string.uuid())
       }
     
       /**
    
  • src/multipart/file.ts+5 1 modified
    @@ -15,6 +15,7 @@ import { moveFile } from '../utils.ts'
     import { SizeValidator } from './validators/size.ts'
     import { ExtensionValidator } from './validators/extensions.ts'
     import type { FileJSON, FileUploadError, FileValidationOptions } from '../types.ts'
    +import string from '@poppinss/utils/string'
     
     /**
      * The file holds the meta/data for an uploaded file, along with
    @@ -217,7 +218,10 @@ export class MultipartFile extends Macroable {
           })
         }
     
    -    options = Object.assign({ name: this.clientName, overwrite: true }, options)
    +    options = Object.assign(
    +      { name: `${string.random(40)}.${this.extname ?? 'unknown'}`, overwrite: true },
    +      options
    +    )
         const filePath = join(location, options.name!)
     
         try {
    
  • tests/body_parser.spec.ts+7 3 modified
    @@ -1070,6 +1070,7 @@ test.group('BodyParser Middleware | multipart', () => {
               await pkgFile.move(fs.basePath)
               assert.equal(pkgFile.state, 'moved')
               res.writeHead(200, { 'content-type': 'application/json' })
    +          res.write(JSON.stringify({ file: pkgFile }))
               res.end()
             } catch (error) {
               res.writeHead(500, { 'content-type': 'application/json' })
    @@ -1078,9 +1079,12 @@ test.group('BodyParser Middleware | multipart', () => {
           })
         })
     
    -    await supertest(server).post('/').attach('package', packageFilePath).expect(200)
    +    const { body } = await supertest(server)
    +      .post('/')
    +      .attach('package', packageFilePath)
    +      .expect(200)
     
    -    const uploadedFileContents = await fs.contents('package.json')
    +    const uploadedFileContents = await fs.contents(body.file.fileName)
         const originalFileContents = await readFile(packageFilePath, 'utf-8')
         assert.equal(uploadedFileContents, originalFileContents)
       })
    @@ -1127,7 +1131,7 @@ test.group('BodyParser Middleware | multipart', () => {
             const pkgFile = ctx.request.file('package')!
     
             try {
    -          await pkgFile.move(fs.basePath, { overwrite: false })
    +          await pkgFile.move(fs.basePath, { name: 'package.json', overwrite: false })
             } catch (error) {
               assert.equal(
                 error.message,
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.