GHSA-3WHC-QVHV-XQJP

Vulnerability from github – Published: 2026-07-01 21:56 – Updated: 2026-07-01 21:56
VLAI
Summary
goshs: WebDAV listener ignores --read-only, --upload-only, and --no-delete mode flags
Details

WebDAV listener ignores --read-only, --upload-only, and --no-delete mode flags

Ecosystem: Go Package: goshs.de/goshs/v2 (github.com/patrickhener/goshs) Affected: <= v2.0.9 (every release that ships the WebDAV handler)

Summary

When goshs is launched with WebDAV enabled (-w), the mode-restriction flags --read-only, --upload-only, and --no-delete are enforced only on the primary HTTP port. The WebDAV port is wired straight to golang.org/x/net/webdav.Handler with no equivalent guard, so an authenticated WebDAV client can PUT, DELETE, MKCOL, MOVE, and COPY despite the operator's stated intent.

Details

httpserver/server.go:207-238 — the WebDAV mux registers only IPWhitelistMiddleware, ServerHeaderMiddleware, and optionally BasicAuthMiddleware. There is no fs.ReadOnly || fs.UploadOnly || fs.NoDelete check on the WebDAV path. The HTTP mux in the same file (lines 134-204) does check these flags on every state-changing route.

Proof of concept

mkdir -p /tmp/r && echo secret > /tmp/r/x.txt
goshs -p 18000 -wp 18001 -w -ro -d /tmp/r -b admin:pw &

curl -u admin:pw -X PUT    http://localhost:18000/y.txt --data x   # 403  (HTTP enforces -ro)
curl -u admin:pw -X PUT    http://localhost:18001/y.txt --data x   # 201  (WebDAV writes anyway)
curl -u admin:pw -X DELETE http://localhost:18001/x.txt            # 204  (WebDAV deletes anyway)
curl -u admin:pw -X MKCOL  http://localhost:18001/pwned/           # 201  (WebDAV creates dir)

Impact

  • Integrity--read-only and --no-delete are silently downgraded to "no protection" on the WebDAV port. Any WebDAV client (curl, cadaver, Windows Explorer, Finder) can overwrite/delete files.
  • Confidentiality--upload-only is also bypassed: WebDAV GET/PROPFIND still return file contents.
  • Trust — operators using goshs -w -ro -d /srv/case-files -b reviewer:pw to deliver engagement artifacts believe the directory is immutable. It isn't.

Suggested fix

Add a small http.HandlerFunc in front of wdHandler that maps WebDAV verbs to the existing mode flags:

wdGuard := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodPut, "MKCOL", "MOVE", "COPY":
        if fs.ReadOnly || fs.UploadOnly { http.Error(w, "read-only", 403); return }
    case http.MethodDelete:
        if fs.ReadOnly || fs.UploadOnly || fs.NoDelete { http.Error(w, "delete disabled", 403); return }
    case http.MethodGet, "PROPFIND", "HEAD":
        if fs.UploadOnly { http.Error(w, "upload-only", 403); return }
    }
    wdHandler.ServeHTTP(w, r)
})

Add regression tests in integration/functions.go covering each mode flag × each WebDAV verb.

Reporter: Nishant Verma. Reproduced live against goshs v2.0.9 (commit 8fc1e91) on 2026-05-27.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2.0.9"
      },
      "package": {
        "ecosystem": "Go",
        "name": "goshs.de/goshs/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-50138"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-284"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-01T21:56:40Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "# WebDAV listener ignores `--read-only`, `--upload-only`, and `--no-delete` mode flags\n\n**Ecosystem:** Go\n**Package:** `goshs.de/goshs/v2` (`github.com/patrickhener/goshs`)\n**Affected:** `\u003c= v2.0.9` (every release that ships the WebDAV handler)\n\n## Summary\n\nWhen `goshs` is launched with WebDAV enabled (`-w`), the mode-restriction flags `--read-only`, `--upload-only`, and `--no-delete` are enforced only on the primary HTTP port. The WebDAV port is wired straight to `golang.org/x/net/webdav.Handler` with no equivalent guard, so an authenticated WebDAV client can `PUT`, `DELETE`, `MKCOL`, `MOVE`, and `COPY` despite the operator\u0027s stated intent.\n\n## Details\n\n[`httpserver/server.go:207-238`](https://github.com/patrickhener/goshs/blob/v2.0.9/httpserver/server.go#L207-L238) \u2014 the WebDAV mux registers only `IPWhitelistMiddleware`, `ServerHeaderMiddleware`, and optionally `BasicAuthMiddleware`. There is no `fs.ReadOnly || fs.UploadOnly || fs.NoDelete` check on the WebDAV path. The HTTP mux in the same file (lines 134-204) does check these flags on every state-changing route.\n\n## Proof of concept\n\n```bash\nmkdir -p /tmp/r \u0026\u0026 echo secret \u003e /tmp/r/x.txt\ngoshs -p 18000 -wp 18001 -w -ro -d /tmp/r -b admin:pw \u0026\n\ncurl -u admin:pw -X PUT    http://localhost:18000/y.txt --data x   # 403  (HTTP enforces -ro)\ncurl -u admin:pw -X PUT    http://localhost:18001/y.txt --data x   # 201  (WebDAV writes anyway)\ncurl -u admin:pw -X DELETE http://localhost:18001/x.txt            # 204  (WebDAV deletes anyway)\ncurl -u admin:pw -X MKCOL  http://localhost:18001/pwned/           # 201  (WebDAV creates dir)\n```\n\n## Impact\n\n- **Integrity** \u2014 `--read-only` and `--no-delete` are silently downgraded to \"no protection\" on the WebDAV port. Any WebDAV client (curl, cadaver, Windows Explorer, Finder) can overwrite/delete files.\n- **Confidentiality** \u2014 `--upload-only` is also bypassed: WebDAV GET/PROPFIND still return file contents.\n- **Trust** \u2014 operators using `goshs -w -ro -d /srv/case-files -b reviewer:pw` to deliver engagement artifacts believe the directory is immutable. It isn\u0027t.\n\n## Suggested fix\n\nAdd a small `http.HandlerFunc` in front of `wdHandler` that maps WebDAV verbs to the existing mode flags:\n\n```go\nwdGuard := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n    switch r.Method {\n    case http.MethodPut, \"MKCOL\", \"MOVE\", \"COPY\":\n        if fs.ReadOnly || fs.UploadOnly { http.Error(w, \"read-only\", 403); return }\n    case http.MethodDelete:\n        if fs.ReadOnly || fs.UploadOnly || fs.NoDelete { http.Error(w, \"delete disabled\", 403); return }\n    case http.MethodGet, \"PROPFIND\", \"HEAD\":\n        if fs.UploadOnly { http.Error(w, \"upload-only\", 403); return }\n    }\n    wdHandler.ServeHTTP(w, r)\n})\n```\n\nAdd regression tests in `integration/functions.go` covering each mode flag \u00d7 each WebDAV verb.\n\nReporter: Nishant Verma. Reproduced live against `goshs v2.0.9` (commit `8fc1e91`) on 2026-05-27.",
  "id": "GHSA-3whc-qvhv-xqjp",
  "modified": "2026-07-01T21:56:40Z",
  "published": "2026-07-01T21:56:40Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/patrickhener/goshs/security/advisories/GHSA-3whc-qvhv-xqjp"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/patrickhener/goshs"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "goshs: WebDAV listener ignores --read-only, --upload-only, and --no-delete mode flags"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…