CVE-2026-40884 - goshs empty-username SFTP authentication bypass
goshs can expose its SFTP service without authentication when it is started
with SFTP enabled and the documented empty-username basic-auth form
-b ':pass'. The configuration is accepted, but affected versions do not
install an SFTP password handler for the empty username case. A remote
unauthenticated attacker can then connect to the SFTP service and read,
upload, rename, or delete files under the configured SFTP root, subject to the
server mode and filesystem permissions.
This is an agentic-context risk because file servers often hold build
artifacts, deployment bundles, logs, support uploads, and generated evidence.
The fix is not only “bump a Go module.” Production remediation needs to prove
that no deploy path still launches vulnerable goshs with -sftp -b ':pass',
and that any exposed SFTP root is treated as potentially modified or read.
Affected versions
- Vulnerable:
github.com/patrickhener/goshs <=1.1.4 - Patched in GHAD: no patched version listed for the v1 module line
- Vulnerable:
github.com/patrickhener/goshs/v2 <2.0.0 - Fixed:
github.com/patrickhener/goshs/v2 2.0.0+ - Beta-line fix:
v2.0.0-beta.6+ - Highest-risk condition: SFTP is enabled and goshs is launched with
empty-user basic auth such as
-b ':pass'.
Indicator-of-exposure
- The repository builds, vendors, packages, deploys, or configures goshs.
- A deployable target resolves to
github.com/patrickhener/goshs <=1.1.4,github.com/patrickhener/goshs/v2 <2.0.0, or a beta release beforev2.0.0-beta.6. - Runtime config, service units, containers, charts, scripts, docs, or
examples enable
-sftp. - Launch flags, environment variables, config templates, runbooks, or tests
use
-b ':pass',--basic-auth ':pass', an empty username with a password, or derived variables that can render to an empty username. - The exposed SFTP root stores release artifacts, logs, backups, generated evidence, customer uploads, deployment manifests, credentials, or other security-sensitive context.
Quick checks:
# macOS / Linux
rg -n "patrickhener/goshs|goshs|go install .*goshs|docker.*goshs|nixpkgs.*goshs" .
rg -n -- "-sftp|--sftp-port|--sftp-keyfile|\\s-b\\s*['\\\"]?:|--basic-auth\\s*['\\\"]?:" .
rg -n "SFTP|sftp|basic.?auth|GOSHS|goshs" Dockerfile* docker-compose*.yml .github charts deploy k8s nix flake.* systemd scripts docs 2>/dev/null
go list -m all | rg "github.com/patrickhener/goshs"
# Windows PowerShell
Get-ChildItem -Recurse -File | Select-String -Pattern "patrickhener/goshs|goshs|go install .*goshs|docker.*goshs|nixpkgs.*goshs"
Get-ChildItem -Recurse -File | Select-String -Pattern "-sftp|--sftp-port|--sftp-keyfile|\\s-b\\s*['\\\"]?:|--basic-auth\\s*['\\\"]?:"
Get-ChildItem -Recurse -File -Include Dockerfile*,docker-compose*.yml,*.yaml,*.yml,*.nix,flake.*,*.service,*.sh,*.ps1,*.md | Select-String -Pattern "SFTP|sftp|basic.?auth|GOSHS|goshs"
go list -m all | Select-String "github.com/patrickhener/goshs"Remediation strategy
- Upgrade goshs to
v2.0.0+or at leastv2.0.0-beta.6+where beta releases are intentionally used. - Migrate away from the unpatched v1 module line when the repository controls Go dependencies or package metadata.
- Remove empty-username SFTP password auth from every launch path. Use a non-empty username with password auth, an approved SFTP key file, or disable SFTP when it is not required.
- Add validation that rejects SFTP launches where password auth has an empty username.
- Add a synthetic integration test that starts goshs with a temp root and proves unauthenticated SFTP sessions are rejected. Do not use production file roots.
- If exposure was possible, review and quarantine the SFTP root contents, compare against trusted source of truth, and rotate credentials or release artifacts that may have been read or modified.
The prompt
Model context: this prompt was generated by GPT 5.5 Extra High reasoning.
You are remediating CVE-2026-40884 (goshs empty-username SFTP authentication
bypass). Produce exactly one output:
- A reviewer-ready PR/change request that upgrades or removes vulnerable
goshs usage, blocks empty-username SFTP auth, adds safe verification, and
documents operator cleanup, or
- TRIAGE.md if this repository does not own an affected goshs deployment,
package, fork, launch path, or safe patch path.
## Rules
- Scope only CVE-2026-40884 / GHSA-c29w-qq4m-2gcv and directly related goshs
SFTP launch hardening.
- Treat SFTP roots, uploaded files, release artifacts, logs, backups, CI
artifacts, deployment bundles, customer uploads, SSH keys, passwords, and
generated evidence as sensitive.
- Do not connect to production or shared SFTP services to prove exposure.
- Do not download, print, commit, or attach real files from an SFTP root.
- Do not preserve `-sftp -b ':pass'` behavior as a supported deployment mode.
- Do not auto-merge.
## Steps
1. Inventory every goshs reference controlled by this repository:
Go manifests and lock data, vendored source, forks, Dockerfiles, compose
files, Helm charts, Kubernetes manifests, Terraform, Nix files, release
automation, package recipes, systemd units, shell scripts, examples,
runbooks, SBOMs, and generated deployment artifacts.
2. Determine every resolved goshs version. A target is vulnerable if it
resolves to:
- `github.com/patrickhener/goshs <=1.1.4`;
- `github.com/patrickhener/goshs/v2 <2.0.0`;
- any beta release before `v2.0.0-beta.6`.
3. Search every launch path for SFTP enablement and empty-username auth:
- `-sftp`;
- `--sftp-port`;
- `--sftp-keyfile`;
- `-b ':pass'`;
- `--basic-auth ':pass'`;
- variables or templates where the username can render empty.
4. If this repository does not build, package, deploy, fork, or configure
goshs, stop with `TRIAGE.md` naming the files checked, the likely runtime
owner if known, and the fixed target `goshs v2.0.0+` or
`v2.0.0-beta.6+`.
5. Upgrade every controlled goshs dependency, binary source, package recipe,
image, SBOM, checksum, and generated deployment artifact to a fixed release.
Prefer stable `v2.0.0+`; use `v2.0.0-beta.6+` only when this repository
intentionally tracks beta releases.
6. Remove empty-username SFTP password auth from every controlled launch path:
- replace `-b ':pass'` with a non-empty service username and secret
reference;
- or switch to an approved `--sftp-keyfile`;
- or disable SFTP when the workflow does not require it.
7. Add fail-closed validation where this repository owns wrappers, charts,
operators, templates, or config generation:
- reject SFTP config when basic-auth username is empty;
- require either a non-empty username/password pair or an approved key file;
- render a clear config error without logging secrets.
8. Add safe verification:
- dependency checks proving no vulnerable goshs version remains;
- static checks proving no generated launch path contains `-sftp -b ':`;
- a synthetic test using a temporary local root that attempts unauthenticated
SFTP and expects rejection;
- secret scanning proving no SFTP passwords or root files were committed.
9. Add a PR body section named `CVE-2026-40884 operator actions` that states:
- goshs versions before and after the change;
- whether SFTP was enabled;
- whether empty-username basic auth was configured;
- every SFTP root path or storage location that may require integrity
review;
- whether uploaded artifacts, release files, logs, backups, or credentials
need quarantine, rebuild, or rotation;
- which access logs should be reviewed for anonymous or unexpected SFTP
sessions during the vulnerable window.
10. Run relevant validation: Go tests, dependency resolution, container build,
Helm/Kustomize/Terraform render, Nix/package build, SBOM refresh, policy
tests, secret scan, and any SFTP wrapper integration tests available in
this repository.
11. Use PR title:
`fix(sec): remediate CVE-2026-40884 in goshs SFTP auth`.
## Stop conditions
- No goshs dependency, binary, package recipe, fork, container, deployment, or
launch path is controlled by this repository.
- All controlled goshs targets already resolve to a fixed release and no
launch path enables empty-username SFTP auth.
- Upgrading goshs requires a platform migration outside this repository.
- Proving exposure would require connecting to a production SFTP service or
reading real files from an SFTP root.
- The SFTP root may contain modified release artifacts or credentials; stop
after documenting quarantine and human operator review.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.Verification - what the reviewer looks for
- No controlled Go module, package recipe, binary source, container, SBOM, or generated artifact resolves to a vulnerable goshs version.
- No runtime launch path can render
-sftpwith an empty basic-auth username. - Config validation fails closed without logging passwords or SFTP root contents.
- Synthetic SFTP tests use disposable local files and prove unauthenticated sessions are rejected.
- Operator actions address SFTP root integrity, artifact quarantine, and credential rotation when exposure was possible.
Watch for
- Updating
go.modwhile Dockerfiles, package recipes, Nix pins, or generated deployment manifests still install an older goshs binary. - Fixing examples or docs while service units and chart templates still render
-b ':pass'. - Treating SFTP as internal-only and skipping network policy or firewall review.
- Tests that prove the vulnerability by connecting to shared infrastructure or reading real uploaded files.
- Logging the replacement SFTP password while adding validation.
References
- GitHub Advisory Database: https://github.com/advisories/GHSA-c29w-qq4m-2gcv
- goshs security advisory: https://github.com/patrickhener/goshs/security/advisories/GHSA-c29w-qq4m-2gcv
- NVD CVE: https://nvd.nist.gov/vuln/detail/CVE-2026-40884