Skip to main content

goshs CVE-2026-50139

MEDIUM
Race Condition (CWE-362)
2026-07-01 https://github.com/patrickhener/goshs GHSA-j48m-h7xq-2xpj
5.9
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
5.9 MEDIUM
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
vuln.today AI
5.9 MEDIUM

Network-accessible endpoint, token possession substitutes for no privilege requirement, race timing yields AC:H; impact is purely confidentiality with no integrity or availability consequence.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

1
Analysis Generated
Jul 01, 2026 - 22:24 vuln.today

DescriptionGitHub Advisory

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:

go
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

bash
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:

go
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.

AnalysisAI

Download-limit enforcement in goshs (Go Simple HTTP Server) v2.0.9 and earlier can be bypassed by racing concurrent HTTP requests against a limited-use share token, allowing a single token to be redeemed more times than the operator configured. The TOCTOU flaw in ShareHandler means every concurrent goroutine observes the same pre-increment Downloaded counter, each passes the limit check, and each is served the file - completely defeating one-shot or low-count share-link controls. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Obtain valid share-link token via disclosure
Delivery
Send parallel GET requests to /?token=<token>
Exploit
Concurrent goroutines race through TOCTOU window
Execution
All requests pass pre-increment limit check
Impact
Files served beyond configured download cap

Vulnerability AssessmentAI

Exploitation Exploitation requires three concrete conditions: (1) the goshs instance has the share-link feature in use and at least one token has been issued with a non-zero `DownloadLimit` - tokens with no limit (`DownloadLimit == -1`) are unaffected by this race since the bypass is only meaningful when a cap is intended; (2) the attacker possesses a valid, unexpired share token - this is the primary prerequisite and is not granted by this vulnerability itself; (3) the attacker can dispatch two or more concurrent HTTP requests within the file-transfer window, which widens naturally with larger files. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The vendor-assigned CVSS 3.1 score of 5.9 Medium (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N) is consistent with the technical facts. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker who obtains a valid goshs share token - through email interception, browser history exposure, or a forwarded link - issues two or more simultaneous HTTP GET requests to `/?token=<token>` using parallel HTTP clients (e.g., background curl processes). All requests enter the TOCTOU window simultaneously, each independently reads `Downloaded < DownloadLimit` as true before any increment is committed, and each receives a 200 response with the full file. …
Remediation No specific patched release version is named in the available advisory data - operators should monitor the goshs GitHub repository (https://github.com/patrickhener/goshs) for a release superseding v2.0.9 that incorporates the fix described in GHSA-j48m-h7xq-2xpj. … Detailed patch versions, workarounds, and compensating controls in full report.

Threat intelligence, references, and detailed analysis are available after sign-in.

Share

CVE-2026-50139 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy