VYPR
High severity8.1NVD Advisory· Published Apr 2, 2026· Updated Apr 15, 2026

CVE-2026-34581

CVE-2026-34581

Description

goshs is a SimpleHTTPServer written in Go. From version 1.1.0 to before version 2.0.0-beta.2, when using the Share Token it is possible to bypass the limited selected file download with all the gosh functionalities, including code exec. This issue has been patched in version 2.0.0-beta.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/patrickhener/goshsGo
>= 1.1.0

Affected products

2
  • Goshs/Goshs2 versions
    cpe:2.3:a:goshs:goshs:2.0.0:beta1:*:*:*:go:*:*+ 1 more
    • cpe:2.3:a:goshs:goshs:2.0.0:beta1:*:*:*:go:*:*
    • cpe:2.3:a:goshs:goshs:*:*:*:*:*:go:*:*range: >=1.1.0,<2.0.0

Patches

1
6fb224ed15c2

Fix webdav bug and address https://github.com/patrickhener/goshs/security/advisories/GHSA-jgfx-74g2-9r6g, a security bug where token can be used to bypass authentication and upload,delete files and run cli commands, if the module is activated. The attacker would need a valid share token beforehand.

https://github.com/patrickhener/goshsPatrick HenerMar 30, 2026via ghsa
4 files changed · +52 5
  • httpserver/handler.go+35 3 modified
    @@ -103,28 +103,46 @@ func (fs *FileServer) doFile(file *os.File, w http.ResponseWriter, req *http.Req
     
     func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Request) bool {
     	if _, ok := req.URL.Query()["smtp"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		fs.handleSMTPAttachment(w, req)
     		return true
     	}
     	if _, ok := req.URL.Query()["goshs-info"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		fs.handleInfo(w)
     		return true
     	}
     	if _, ok := req.URL.Query()["mkdir"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		fs.handleMkdir(w, req)
     		return true
     	}
     	if _, ok := req.URL.Query()["ws"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		fs.socket(w, req)
     		return true
     	}
     	if _, ok := req.URL.Query()["cbDown"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if !fs.NoClipboard && !fs.Invisible {
     			fs.cbDown(w, req)
     			return true
     		}
     	}
     	if _, ok := req.URL.Query()["bulk"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if !fs.Invisible {
     			fs.bulkDownload(w, req)
     		} else {
    @@ -133,6 +151,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
     		return true
     	}
     	if _, ok := req.URL.Query()["static"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if !fs.Invisible {
     			fs.static(w, req)
     		} else {
    @@ -141,6 +162,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
     		return true
     	}
     	if _, ok := req.URL.Query()["embedded"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if err := fs.embedded(w, req); err != nil {
     			if !fs.Invisible {
     				body := fs.emitCollabEvent(req, http.StatusNotFound)
    @@ -155,6 +179,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
     		return true
     	}
     	if _, ok := req.URL.Query()["delete"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if !fs.ReadOnly && !fs.UploadOnly && !fs.NoDelete {
     			fs.deleteFile(w, req)
     			return true
    @@ -164,6 +191,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
     		}
     	}
     	if _, ok := req.URL.Query()["share"]; ok {
    +		if denyForTokenAccess(w, req) {
    +			return true
    +		}
     		if !fs.Invisible {
     			fs.CreateShareHandler(w, req)
     		} else {
    @@ -836,9 +866,11 @@ func (fs *FileServer) ShareHandler(w http.ResponseWriter, r *http.Request) {
     	entry.Downloaded++
     
     	fs.SharedLinks[token] = entry
    -	if fs.SharedLinks[token].Downloaded >= fs.SharedLinks[token].DownloadLimit {
    -		// Remove the share link from map to keep it clean
    -		delete(fs.SharedLinks, token)
    +	if fs.SharedLinks[token].DownloadLimit != -1 {
    +		if fs.SharedLinks[token].Downloaded >= fs.SharedLinks[token].DownloadLimit {
    +			// Remove the share link from map to keep it clean
    +			delete(fs.SharedLinks, token)
    +		}
     	}
     }
     
    
  • httpserver/helper.go+8 0 modified
    @@ -77,3 +77,11 @@ func GenerateQRCode(uri string) string {
     
     	return fmt.Sprintf("data:image/png;base64,%s", encoded)
     }
    +
    +func denyForTokenAccess(w http.ResponseWriter, r *http.Request) bool {
    +	if r.URL.Query().Get("token") != "" {
    +		http.Error(w, "Forbidden", http.StatusForbidden)
    +		return true
    +	}
    +	return false
    +}
    
  • httpserver/server.go+6 0 modified
    @@ -93,13 +93,19 @@ func (fs *FileServer) SetupMux(mux *CustomMux, what string) string {
     		// Define routes
     		mux.HandleFunc("POST /", func(w http.ResponseWriter, r *http.Request) {
     			if strings.HasSuffix(r.URL.Path, "/upload") {
    +				if denyForTokenAccess(w, r) {
    +					return
    +				}
     				fs.upload(w, r)
     				runtime.GC()
     			} else {
     				fs.logOnly(w, r)
     			}
     		})
     		mux.HandleFunc("PUT /", func(w http.ResponseWriter, r *http.Request) {
    +			if denyForTokenAccess(w, r) {
    +				return
    +			}
     			fs.put(w, r)
     		})
     		mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    
  • server/server.go+3 2 modified
    @@ -28,8 +28,9 @@ func StartAll(opts *options.Options) {
     
     	// webdav
     	if opts.WebDav {
    -		httpSrv.Port = opts.WebDavPort
    -		go httpSrv.Start("webdav")
    +		webdavSrv := httpserver.NewHttpServer(opts, hub, clip, wl, *wh)
    +		webdavSrv.WebdavPort = opts.WebDavPort
    +		go webdavSrv.Start("webdav")
     	}
     
     	if opts.SFTP {
    

Vulnerability mechanics

Generated by null/stub 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.