VYPR
Moderate severityNVD Advisory· Published Feb 1, 2024· Updated Oct 17, 2024

Bref Uploaded Files Not Deleted in Event-Driven Functions

CVE-2024-24752

Description

Bref enable serverless PHP on AWS Lambda. When Bref is used with the Event-Driven Function runtime and the handler is a RequestHandlerInterface, then the Lambda event is converted to a PSR7 object. During the conversion process, if the request is a MultiPart, each part is parsed and for each which contains a file, it is extracted and saved in /tmp with a random filename starting with bref_upload_. The flow mimics what plain PHP does but it does not delete the temporary files when the request has been processed. An attacker could fill the Lambda instance disk by performing multiple MultiPart requests containing files. This vulnerability is patched in 2.1.13.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Bref serverless PHP on AWS Lambda fails to delete temporary uploaded files in Event-Driven Functions, allowing disk exhaustion via multipart requests.

CVE-2024-24752 is a vulnerability in Bref, a framework that enables serverless PHP on AWS Lambda. When using the Event-Driven Function runtime with a RequestHandlerInterface handler, incoming HTTP Lambda events are converted to PSR-7 objects. During this conversion, multipart/form-data requests are parsed, and each file part is saved to /tmp with a filename prefixed with bref_upload_ [1][2]. Critically, the affected code does not delete these temporary files after processing, leading to disk space accumulation on the Lambda instance [2].

The attack surface is the HTTP endpoint of an Event-Driven Function. An attacker can send multiple multipart requests containing files; each request will create a temporary file in /tmp. No authentication is required beyond what is normally needed to reach the function. As the function processes requests, the /tmp directory fills up with these undeleted files, potentially exhausting the ephemeral storage available to the Lambda execution environment [1][2].

Successful exploitation results in a denial-of-service (DoS) condition. By filling the Lambda instance's disk, the attacker can cause the function to fail when it attempts to write further files or when the operating system runs out of space, preventing legitimate requests from being processed [1]. The vulnerability is classified with a CVSS v3.1 base score of 5.3 (Medium), reflecting the network-based, low-complexity attack that requires no privileges or user interaction [1].

The vulnerability is patched in Bref version 2.1.13 [1][2]. The fix ensures temporary files are properly cleaned up after request processing; it also improves the handling of malformed multipart bodies [3]. Users are strongly advised to update to the patched version or apply the relevant commit to mitigate this issue.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
bref/brefPackagist
< 2.1.132.1.13

Affected products

2

Patches

1
350788de1288

Support malformed multipart body

https://github.com/brefphp/brefMatthieu NapoliJan 31, 2024via ghsa
4 files changed · +40 27
  • src/Event/Http/Psr7Bridge.php+36 23 modified
    @@ -93,36 +93,49 @@ public static function convertResponse(ResponseInterface $response): HttpRespons
             return new HttpResponse($body, $response->getHeaders(), $response->getStatusCode());
         }
     
    +    /**
    +     * @return array{0: array<string, UploadedFile>, 1: array<string, mixed>|null}
    +     */
         private static function parseBodyAndUploadedFiles(HttpRequestEvent $event): array
         {
    -        $bodyString = $event->getBody();
    -        $files = [];
    -        $parsedBody = null;
             $contentType = $event->getContentType();
    -        if ($contentType !== null && $event->getMethod() === 'POST') {
    -            if (str_starts_with($contentType, 'application/x-www-form-urlencoded')) {
    -                parse_str($bodyString, $parsedBody);
    -            } else {
    -                $document = new Part("Content-type: $contentType\r\n\r\n" . $bodyString);
    -                if ($document->isMultiPart()) {
    -                    $parsedBody = [];
    -                    foreach ($document->getParts() as $part) {
    -                        if ($part->isFile()) {
    +        if ($contentType === null || $event->getMethod() !== 'POST') {
    +            return [[], null];
    +        }
    +
    +        if (str_starts_with($contentType, 'application/x-www-form-urlencoded')) {
    +            $parsedBody = [];
    +            parse_str($event->getBody(), $parsedBody);
    +            return [[], $parsedBody];
    +        }
    +
    +        // Parse the body as multipart/form-data
    +        $document = new Part("Content-type: $contentType\r\n\r\n" . $event->getBody());
    +        if (!$document->isMultiPart()) {
    +            return [[], null];
    +        }
    +        $files = [];
    +        $queryString = '';
    +        foreach ($document->getParts() as $part) {
    +            if ($part->isFile()) {
                                 $tmpPath = tempnam(sys_get_temp_dir(), self::UPLOADED_FILES_PREFIX);
    -                            if ($tmpPath === false) {
    -                                throw new RuntimeException('Unable to create a temporary directory');
    -                            }
    -                            file_put_contents($tmpPath, $part->getBody());
    -                            $file = new UploadedFile($tmpPath, filesize($tmpPath), UPLOAD_ERR_OK, $part->getFileName(), $part->getMimeType());
    -
    -                            self::parseKeyAndInsertValueInArray($files, $part->getName(), $file);
    -                        } else {
    -                            self::parseKeyAndInsertValueInArray($parsedBody, $part->getName(), $part->getBody());
    -                        }
    -                    }
    +                if ($tmpPath === false) {
    +                    throw new RuntimeException('Unable to create a temporary directory');
                     }
    +                file_put_contents($tmpPath, $part->getBody());
    +                $file = new UploadedFile($tmpPath, filesize($tmpPath), UPLOAD_ERR_OK, $part->getFileName(), $part->getMimeType());
    +                self::parseKeyAndInsertValueInArray($files, $part->getName(), $file);
    +            } else {
    +                // Temporarily store as a query string so that we can use PHP's native parse_str function to parse keys
    +                $queryString .= urlencode($part->getName()) . '=' . urlencode($part->getBody()) . '&';
                 }
             }
    +        if ($queryString !== '') {
    +            $parsedBody = [];
    +            parse_str($queryString, $parsedBody);
    +        } else {
    +            $parsedBody = null;
    +        }
             return [$files, $parsedBody];
         }
     
    
  • tests/Event/Http/CommonHttpTest.php+2 2 modified
    @@ -401,7 +401,7 @@ public function test POST request with multipart file uploads(int $version
     --testBoundary--\r
     ";
             $this->assertBody($body);
    -        $this->assertParsedBody([]);
    +        $this->assertParsedBody(null);
             $this->assertUploadedFile(
                 'foo',
                 'lorem.txt',
    @@ -554,7 +554,7 @@ abstract protected function assertUri(string $expected): void;
     
         abstract protected function assertHasMultiHeader(bool $expected): void;
     
    -    abstract protected function assertParsedBody(array $expected): void;
    +    abstract protected function assertParsedBody(array|null $expected): void;
     
         abstract protected function assertSourceIp(string $expected): void;
     
    
  • tests/Event/Http/HttpRequestEventTest.php+1 1 modified
    @@ -112,7 +112,7 @@ protected function assertSourceIp(string $expected): void
             $this->assertEquals($expected, $this->event->getSourceIp());
         }
     
    -    protected function assertParsedBody(array $expected): void
    +    protected function assertParsedBody(array|null $expected): void
         {
             // Not applicable here since the class doesn't parse the body
         }
    
  • tests/Event/Http/Psr7BridgeTest.php+1 1 modified
    @@ -123,7 +123,7 @@ protected function assertHasMultiHeader(bool $expected): void
             // Not applicable here
         }
     
    -    protected function assertParsedBody(array $expected): void
    +    protected function assertParsedBody(array|null $expected): void
         {
             $this->assertEquals($expected, $this->request->getParsedBody());
         }
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.