GHSA-3CCM-4QQ2-5WRP is a medium-severity security vulnerability in github.com/edgelesssys/contrast (go), affecting versions <= 1.20.0. It is fixed in 1.21.0.
Summary ciphertextContainer.UnmarshalJSON decodes the third :-separated component of a vault:vX:base64... ciphertext and then unconditionally takes a 12-byte prefix slice for the AES-GCM nonce: c.nonce = fullCiphertext[:aesGCMNonceSize]. If the decoded blob is shorter than 12 bytes, the slice expression panics. The panic happens before any cryptographic operation, while the JSON body of the request is still being parsed inside the request handler. Because the handler is invoked from net/http's standard handler goroutine, the panic is recovered to a 500 response, but the request handler aborts mid-execution and the recovered panic appears in the Coordinator's logs. An authenticated workload that holds a valid mesh certificate for any WorkloadSecretID can trigger the panic at will, producing log spam, request-failure metrics, and a slow but cheap denial of service against the transit-engine endpoint. Details the panicking slice coordinator/internal/transitengineapi/crypto.go:64-88: aesGCMNonceSize = 12 (defined at line 33). There is no length check on fullCiphertext. If parts[2] decodes to fewer than 12 bytes (which happens for any base64 string shorter than ~16 characters), the slice expression fullCiphertext[:aesGCMNonceSize] triggers Go's runtime panic runtime error: slice bounds out of range [:12] with length N. UnmarshalJSON is reached from parseRequest: which is called inside getDecryptHandler (line 178-237) before any other processing. auth requirement is real but trivial to satisfy for any registered workload The transit-engine HTTP server (transitengineapi.go:74-100) configures tls.RequireAndVerifyClientCert with the Coordinator's mesh CA pool. The handler is wrapped by authorizationMiddleware (line 348-357) which calls authorizeWorkloadSecret (line 241-254). That function reads the WorkloadSecretOID extension from the peer cert and requires it to match the URL path's {name} segment. Any workload that has gone through the normal initializer / meshapi flow (coordinator/internal/meshapi/meshapi.go:71-119) and has a non-empty WorkloadSecretID in its PolicyEntry is issued a mesh cert with the matching extension, so the path-name authorisation is automatically satisfied for whichever workloadSecretID the manifest assigned to that workload. There is no rate limiting, no proof-of-work, and no audit log on triggering the panic. what happens after the panic net/http wraps each handler in a recovered goroutine, so the panic does not crash the Coordinator process. Instead: The Go runtime captures the panic, logs http: panic serving <peer>: runtime error: slice bounds out of range to stderr together with a goroutine stack trace. The connection is hung up without a response body (http.Server.serve calls c.close() in the recovery path). The grpc-prometheus / handler metrics (registered via promRegistry) record the request as failed. The recovered panic appears in the Coordinator's logs / journald, creating noise that an operator monitoring a real attack would have to filter out. A workload that wants to amplify the impact can: Loop the request to fill the journal with stack traces (cheap operation per request, expensive log volume). Combine with a second valid workload identity to bypass any per-cert rate limiting added later. Use the panic stack trace (which contains internal source paths) as a fingerprint to determine the exact Coordinator version in lieu of a /version endpoint. The panic also avoids returning a JSON error body to the caller, so callers that depend on a structured error are forced into a less informative failure mode (HTTP-level connection close). PoC The bug is deterministic. Drop the following test into coordinator/internal/transitengineapi/crypto_test.go: End-to-end against a running Coordinator (omitted for static review; would require a Contrast cluster and a mesh-certificate-holding workload): Impact Soft denial of service against the transit-engine endpoint per workload identity. The Coordinator process survives because of net/http's panic recovery, but each panicked request consumes CPU for the recovery / stack dump and floods the operator's logs. Information disclosure via stack trace in the Coordinator log. The trace pins the Coordinator binary version, the build path of the transitengineapi package, and exact line numbers of internal source. This is a low-grade fingerprint, but it is leaked even to operators who would normally only see the binary version through controlled means. Loss of structured error reporting: legitimate decrypt requests sharing the panicked log lines may be harder to attribute, and the API consumer sees a connection-close instead of a 4xx response, masking the cause. CVSS rationale: AV:N, AC:L, PR:L (any workload with a transit-engine permission can do this), UI:N, S:U, C:N / I:N / A:L (low availability impact: log noise + per-request CPU cost; no full DoS because Go's HTTP panic recovery keeps the process up). Score 3.1. Recommended Fix Validate the decoded length before slicing. The minimal change at coordinator/internal/transitengineapi/crypto.go:81-87: A defence-in-depth tightening would also reject ciphertexts with len(fullCiphertext) <= aesGCMNonceSize (which would yield an empty actual ciphertext that AES-GCM open would later reject anyway, but a sharper boundary fails earlier with a clearer error). Add a unit test along the lines of the PoC that asserts a clean error rather than a panic.
GHSA-3CCM-4QQ2-5WRP has a CVSS score of 4.3 (Medium). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment.
A fixed version is available (1.21.0). Upgrading removes the vulnerable code path.
go
github.com/edgelesssys/contrast (<= 1.20.0)github.com/edgelesssys/contrast → 1.21.0 (go)Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter instead of chasing every advisory.
Kodem's runtime-powered SCA identifies whether GHSA-3CCM-4QQ2-5WRP is reachable in your applications. Explore open-source security for your team.
See if GHSA-3CCM-4QQ2-5WRP is reachable in your applications. Get a demo
Already deployed Kodem? See GHSA-3CCM-4QQ2-5WRP in your environment →Upgrade github.com/edgelesssys/contrast to 1.21.0 or later to resolve this vulnerability.
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
GHSA-3CCM-4QQ2-5WRP is a medium-severity security vulnerability in github.com/edgelesssys/contrast (go), affecting versions <= 1.20.0. It is fixed in 1.21.0.
GHSA-3CCM-4QQ2-5WRP has a CVSS score of 4.3 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
github.com/edgelesssys/contrast (go) versions <= 1.20.0 is affected.
Yes. GHSA-3CCM-4QQ2-5WRP is fixed in 1.21.0. Upgrade to this version or later.
Whether GHSA-3CCM-4QQ2-5WRP is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
Upgrade github.com/edgelesssys/contrast to 1.21.0 or later.