{
    "document": {
        "category": "csaf_base",
        "csaf_version": "2.0",
        "distribution": {
            "tlp": {
                "label": "WHITE"
            }
        },
        "lang": "en",
        "notes": [
            {
                "category": "legal_disclaimer",
                "text": "The Netherlands Cyber Security Center (henceforth: NCSC-NL) maintains this portal to enhance access to its information and vulnerabilities. The use of this information is subject to the following terms and conditions:\n\nThe vulnerabilities disclosed in this portal are gathered by NCSC-NL from a variety of open sources, which the user can retrieve from other platforms. NCSC-NL makes every reasonable effort to ensure that the content of this portal is kept up to date, and that it is accurate and complete. Nevertheless, NCSC-NL cannot entirely rule out the possibility of errors, and therefore cannot give any warranty in respect of its completeness, accuracy or real-time keeping up-to-date. NCSC-NL does not control nor guarantee the accuracy, relevance, timeliness or completeness of information obtained from these external sources. The vulnerabilities disclosed in this portal are intended solely for the convenience of professional parties to take appropriate measures to manage the risks posed to the cybersecurity. No rights can be derived from the information provided therein.\n\nNCSC-NL and the Kingdom of the Netherlands assume no legal liability or responsibility for any damage resulting from either the use or inability of use of the vulnerabilities disclosed in this portal. This includes damage resulting from the inaccuracy of incompleteness of the information contained in it.\nThe information on this page is subject to Dutch law. All disputes related to or arising from the use of this portal regarding the disclosure of vulnerabilities will be submitted to the competent court in The Hague. This choice of means also applies to the court in summary proceedings."
            }
        ],
        "publisher": {
            "category": "coordinator",
            "contact_details": "cert@ncsc.nl",
            "name": "National Cyber Security Centre",
            "namespace": "https://www.ncsc.nl/"
        },
        "title": "CVE-2026-100836",
        "tracking": {
            "current_release_date": "2026-10-20T13:54:46.244577Z",
            "generator": {
                "date": "2026-02-17T15:00:00Z",
                "engine": {
                    "name": "V.E.L.M.A",
                    "version": "1.7"
                }
            },
            "id": "CVE-2026-100836",
            "initial_release_date": "2026-09-27T02:25:45.184189Z",
            "revision_history": [
                {
                    "date": "2026-09-27T02:25:45.184189Z",
                    "number": "1",
                    "summary": "CVE created.| Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-09-27T02:25:46.975268Z",
                    "number": "2",
                    "summary": "NCSC Score created."
                },
                {
                    "date": "2026-09-27T12:14:08.652120Z",
                    "number": "3",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products connected (1).| References created (4).| CWES updated (1)."
                },
                {
                    "date": "2026-09-27T12:14:10.992456Z",
                    "number": "4",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-09-27T15:15:10.060167Z",
                    "number": "5",
                    "summary": "EPSS created.| Unknown change."
                },
                {
                    "date": "2026-09-27T18:13:04.524479Z",
                    "number": "6",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| References created (3)."
                },
                {
                    "date": "2026-09-27T18:13:04.847748Z",
                    "number": "7",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products created (1).| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-09-28T06:45:16.616366Z",
                    "number": "8",
                    "summary": "Products removed (1)."
                },
                {
                    "date": "2026-09-28T12:42:07.342586Z",
                    "number": "9",
                    "summary": "CVSS created.| CWES created (1).| Products created (1).| References created (2).| Description created for source.| Unknown change."
                },
                {
                    "date": "2026-09-28T12:42:11.436190Z",
                    "number": "10",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-09-28T16:38:44.568008Z",
                    "number": "11",
                    "summary": "Unknown change."
                },
                {
                    "date": "2026-09-29T16:13:19.821040Z",
                    "number": "12",
                    "summary": "EPSS created.| Unknown change."
                },
                {
                    "date": "2026-09-29T16:13:25.633975Z",
                    "number": "13",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-10-20T13:54:28.607604Z",
                    "number": "14",
                    "summary": "Products created (1)."
                }
            ],
            "status": "interim",
            "version": "14"
        }
    },
    "product_tree": {
        "branches": [
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:semver/<=1.20.0",
                                "product": {
                                    "name": "vers:semver/<=1.20.0",
                                    "product_id": "CSAFPID-9478892"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=0|<1.21.0",
                                "product": {
                                    "name": "vers:unknown/>=0|<1.21.0",
                                    "product_id": "CSAFPID-9475361"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v1.20.0",
                                "product": {
                                    "name": "vers:unknown/v1.20.0",
                                    "product_id": "CSAFPID-9474607"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "contrast"
                    }
                ],
                "category": "vendor",
                "name": "edgelesssys"
            }
        ]
    },
    "vulnerabilities": [
        {
            "cve": "CVE-2026-100836",
            "cwe": {
                "id": "CWE-129",
                "name": "Improper Validation of Array Index"
            },
            "notes": [
                {
                    "category": "description",
                    "text": "Contrast through 1.20.0 contains a panic vulnerability in the transit-engine endpoint's ciphertextContainer.UnmarshalJSON function that fails to validate decoded ciphertext length before slicing. An authenticated workload with a valid mesh certificate can trigger a runtime panic by submitting a short base64-encoded ciphertext, causing log spam and request failures without crashing the process.",
                    "title": "cveprojectv5 - https://www.cve.org/CVERecord?id=CVE-2026-100836"
                },
                {
                    "category": "description",
                    "text": "Contrast through 1.20.0 contains a panic vulnerability in the transit-engine endpoint's ciphertextContainer.UnmarshalJSON function that fails to validate decoded ciphertext length before slicing. An authenticated workload with a valid mesh certificate can trigger a runtime panic by submitting a short base64-encoded ciphertext, causing log spam and request failures without crashing the process.",
                    "title": "osvgit - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/GIT%2FCVE-2026-100836.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "## Summary\n\n`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.\n\n## Details\n\n### the panicking slice\n\n`coordinator/internal/transitengineapi/crypto.go:64-88`:\n\n```go\n// UnmarshalJSON umarshalls a json string to a ciphertextContainer holding the version prefix,\n// decoded base64 nonce and ciphertext.\nfunc (c *ciphertextContainer) UnmarshalJSON(data []byte) error {\n\tvar encoded string\n\tif err := json.Unmarshal(data, &encoded); err != nil {\n\t\treturn err\n\t}\n\t// Split \"vault:vX:base64\" format\n\tparts := strings.SplitN(encoded, \":\", 3)\n\tif len(parts) < 3 {\n\t\treturn fmt.Errorf(\"invalid ciphertext format\")\n\t}\n\tversion, err := extractVersion(parts[1])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"ciphertext version: %w\", err)\n\t}\n\tc.keyVersion = version\n\tfullCiphertext, err := base64.StdEncoding.DecodeString(parts[2])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"decoding ciphertext: %w\", err)\n\t}\n\tc.nonce = fullCiphertext[:aesGCMNonceSize]      // PANIC when len(fullCiphertext) < 12\n\tc.ciphertext = fullCiphertext[aesGCMNonceSize:]\n\treturn nil\n}\n```\n\n`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`.\n\n`UnmarshalJSON` is reached from `parseRequest`:\n\n```go\n// coordinator/internal/transitengineapi/transitengineapi.go:292-302\nfunc parseRequest(r *http.Request, into any) error {\n\tdefer r.Body.Close()\n\tif err := validateContentType(r); err != nil {\n\t\treturn err\n\t}\n\tif err := json.NewDecoder(r.Body).Decode(into); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n```\n\nwhich is called inside `getDecryptHandler` (line 178-237) before any other processing.\n\n### auth requirement is real but trivial to satisfy for any registered workload\n\nThe 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.\n\nAny 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.\n\n### what happens after the panic\n\n`net/http` wraps each handler in a recovered goroutine, so the panic does not crash the Coordinator process. Instead:\n\n1. 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.\n2. The connection is hung up without a response body (`http.Server.serve` calls `c.close()` in the recovery path).\n3. The grpc-prometheus / handler metrics (registered via `promRegistry`) record the request as failed.\n4. The recovered panic appears in the Coordinator's logs / journald, creating noise that an operator monitoring a real attack would have to filter out.\n\nA workload that wants to amplify the impact can:\n\n* Loop the request to fill the journal with stack traces (cheap operation per request, expensive log volume).\n* Combine with a second valid workload identity to bypass any per-cert rate limiting added later.\n* 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.\n\nThe 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).\n\n## PoC\n\nThe bug is deterministic. Drop the following test into `coordinator/internal/transitengineapi/crypto_test.go`:\n\n```go\nfunc TestCiphertextContainer_UnmarshalJSON_ShortBlobPanics(t *testing.T) {\n\t// \"AAAA\" base64-decodes to 3 bytes, well under aesGCMNonceSize=12.\n\tbody := []byte(`\"vault:v1:AAAA\"`)\n\tdefer func() {\n\t\tif r := recover(); r == nil {\n\t\t\tt.Fatalf(\"expected panic, got nil\")\n\t\t}\n\t}()\n\tvar c ciphertextContainer\n\t_ = c.UnmarshalJSON(body) // panics: slice bounds out of range [:12] with length 3\n}\n```\n\nEnd-to-end against a running Coordinator (omitted for static review; would require a Contrast cluster and a mesh-certificate-holding workload):\n\n```bash\n$ curl -k --cert workload.crt --key workload.key \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"ciphertext\":\"vault:v1:AAAA\",\"associated_data\":\"\"}' \\\n    https://coordinator:8200/v1/transit/decrypt/<my-workload-secret-id>\n\n# Connection: closed without HTTP response body.\n# Coordinator log:\n# http: panic serving 10.0.0.5:54321: runtime error: slice bounds out of range [:12] with length 3\n# goroutine 4711 [running]:\n# net/http.(*conn).serve.func1(...)\n#         net/http/server.go:1883 +0xb0\n# panic({0x...?, 0x...?})\n#         runtime/panic.go:770 +0x132\n# github.com/edgelesssys/contrast/coordinator/internal/transitengineapi.(*ciphertextContainer).UnmarshalJSON(...)\n#         coordinator/internal/transitengineapi/crypto.go:85 +0x...\n```\n\n## Impact\n\n* **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.\n* **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.\n* **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.\n\nCVSS 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`.\n\n## Recommended Fix\n\nValidate the decoded length before slicing. The minimal change at `coordinator/internal/transitengineapi/crypto.go:81-87`:\n\n```go\nfullCiphertext, err := base64.StdEncoding.DecodeString(parts[2])\nif err != nil {\n\treturn fmt.Errorf(\"decoding ciphertext: %w\", err)\n}\nif len(fullCiphertext) < aesGCMNonceSize {\n\treturn fmt.Errorf(\"ciphertext is too short: got %d bytes, expected at least %d for the nonce\", len(fullCiphertext), aesGCMNonceSize)\n}\nc.nonce = fullCiphertext[:aesGCMNonceSize]\nc.ciphertext = fullCiphertext[aesGCMNonceSize:]\nreturn nil\n```\n\nA 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.",
                    "title": "osvgo - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-3ccm-4qq2-5wrp.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "Constrata's coordinator transit engine `ciphertextContainer.UnmarshalJSON` panics on attacker-controlled short ciphertexts in github.com/edgelesssys/contrast",
                    "title": "osvgo - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-5864.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "Contrast through 1.20.0 contains a panic vulnerability in the transit-engine endpoint's ciphertextContainer.UnmarshalJSON function that fails to validate decoded ciphertext length before slicing. An authenticated workload with a valid mesh certificate can trigger a runtime panic by submitting a short base64-encoded ciphertext, causing log spam and request failures without crashing the process.",
                    "title": "nvd - https://nvd.nist.gov/vuln/detail/CVE-2026-100836"
                },
                {
                    "category": "description",
                    "text": "Constrata's coordinator transit engine `ciphertextContainer.UnmarshalJSON` panics on attacker-controlled short ciphertexts in github.com/edgelesssys/contrast",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-5864.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "## Summary\n\n`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.\n\n## Details\n\n### the panicking slice\n\n`coordinator/internal/transitengineapi/crypto.go:64-88`:\n\n```go\n// UnmarshalJSON umarshalls a json string to a ciphertextContainer holding the version prefix,\n// decoded base64 nonce and ciphertext.\nfunc (c *ciphertextContainer) UnmarshalJSON(data []byte) error {\n\tvar encoded string\n\tif err := json.Unmarshal(data, &encoded); err != nil {\n\t\treturn err\n\t}\n\t// Split \"vault:vX:base64\" format\n\tparts := strings.SplitN(encoded, \":\", 3)\n\tif len(parts) < 3 {\n\t\treturn fmt.Errorf(\"invalid ciphertext format\")\n\t}\n\tversion, err := extractVersion(parts[1])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"ciphertext version: %w\", err)\n\t}\n\tc.keyVersion = version\n\tfullCiphertext, err := base64.StdEncoding.DecodeString(parts[2])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"decoding ciphertext: %w\", err)\n\t}\n\tc.nonce = fullCiphertext[:aesGCMNonceSize]      // PANIC when len(fullCiphertext) < 12\n\tc.ciphertext = fullCiphertext[aesGCMNonceSize:]\n\treturn nil\n}\n```\n\n`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`.\n\n`UnmarshalJSON` is reached from `parseRequest`:\n\n```go\n// coordinator/internal/transitengineapi/transitengineapi.go:292-302\nfunc parseRequest(r *http.Request, into any) error {\n\tdefer r.Body.Close()\n\tif err := validateContentType(r); err != nil {\n\t\treturn err\n\t}\n\tif err := json.NewDecoder(r.Body).Decode(into); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n```\n\nwhich is called inside `getDecryptHandler` (line 178-237) before any other processing.\n\n### auth requirement is real but trivial to satisfy for any registered workload\n\nThe 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.\n\nAny 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.\n\n### what happens after the panic\n\n`net/http` wraps each handler in a recovered goroutine, so the panic does not crash the Coordinator process. Instead:\n\n1. 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.\n2. The connection is hung up without a response body (`http.Server.serve` calls `c.close()` in the recovery path).\n3. The grpc-prometheus / handler metrics (registered via `promRegistry`) record the request as failed.\n4. The recovered panic appears in the Coordinator's logs / journald, creating noise that an operator monitoring a real attack would have to filter out.\n\nA workload that wants to amplify the impact can:\n\n* Loop the request to fill the journal with stack traces (cheap operation per request, expensive log volume).\n* Combine with a second valid workload identity to bypass any per-cert rate limiting added later.\n* 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.\n\nThe 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).\n\n## PoC\n\nThe bug is deterministic. Drop the following test into `coordinator/internal/transitengineapi/crypto_test.go`:\n\n```go\nfunc TestCiphertextContainer_UnmarshalJSON_ShortBlobPanics(t *testing.T) {\n\t// \"AAAA\" base64-decodes to 3 bytes, well under aesGCMNonceSize=12.\n\tbody := []byte(`\"vault:v1:AAAA\"`)\n\tdefer func() {\n\t\tif r := recover(); r == nil {\n\t\t\tt.Fatalf(\"expected panic, got nil\")\n\t\t}\n\t}()\n\tvar c ciphertextContainer\n\t_ = c.UnmarshalJSON(body) // panics: slice bounds out of range [:12] with length 3\n}\n```\n\nEnd-to-end against a running Coordinator (omitted for static review; would require a Contrast cluster and a mesh-certificate-holding workload):\n\n```bash\n$ curl -k --cert workload.crt --key workload.key \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"ciphertext\":\"vault:v1:AAAA\",\"associated_data\":\"\"}' \\\n    https://coordinator:8200/v1/transit/decrypt/<my-workload-secret-id>\n\n# Connection: closed without HTTP response body.\n# Coordinator log:\n# http: panic serving 10.0.0.5:54321: runtime error: slice bounds out of range [:12] with length 3\n# goroutine 4711 [running]:\n# net/http.(*conn).serve.func1(...)\n#         net/http/server.go:1883 +0xb0\n# panic({0x...?, 0x...?})\n#         runtime/panic.go:770 +0x132\n# github.com/edgelesssys/contrast/coordinator/internal/transitengineapi.(*ciphertextContainer).UnmarshalJSON(...)\n#         coordinator/internal/transitengineapi/crypto.go:85 +0x...\n```\n\n## Impact\n\n* **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.\n* **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.\n* **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.\n\nCVSS 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`.\n\n## Recommended Fix\n\nValidate the decoded length before slicing. The minimal change at `coordinator/internal/transitengineapi/crypto.go:81-87`:\n\n```go\nfullCiphertext, err := base64.StdEncoding.DecodeString(parts[2])\nif err != nil {\n\treturn fmt.Errorf(\"decoding ciphertext: %w\", err)\n}\nif len(fullCiphertext) < aesGCMNonceSize {\n\treturn fmt.Errorf(\"ciphertext is too short: got %d bytes, expected at least %d for the nonce\", len(fullCiphertext), aesGCMNonceSize)\n}\nc.nonce = fullCiphertext[:aesGCMNonceSize]\nc.ciphertext = fullCiphertext[aesGCMNonceSize:]\nreturn nil\n```\n\nA 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.",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-3ccm-4qq2-5wrp.json?alt=media"
                },
                {
                    "category": "other",
                    "text": "0.00147",
                    "title": "EPSS"
                },
                {
                    "category": "other",
                    "text": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
                    "title": "CVSSV4"
                },
                {
                    "category": "other",
                    "text": "5.3",
                    "title": "CVSSV4 base score"
                },
                {
                    "category": "other",
                    "text": "4.0",
                    "title": "NCSC Score"
                },
                {
                    "category": "other",
                    "text": "There is cwe data available from source Nvd, The value of the most recent CVSS (V3) score",
                    "title": "NCSC Score top decreasing factors"
                }
            ],
            "product_status": {
                "known_affected": [
                    "CSAFPID-9475361",
                    "CSAFPID-9478892",
                    "CSAFPID-9474607"
                ]
            },
            "references": [
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/GIT%2FCVE-2026-100836.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-3ccm-4qq2-5wrp.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-5864.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - nvd",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-100836"
                },
                {
                    "category": "external",
                    "summary": "Source - ncscclear",
                    "url": "https://vulnerabilities.ncsc.nl/manual/CVE-2026-100836"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss"
                },
                {
                    "category": "external",
                    "summary": "Source - cveprojectv5",
                    "url": "https://www.cve.org/CVERecord?id=CVE-2026-100836"
                },
                {
                    "category": "external",
                    "summary": "Source - osvgo",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-3ccm-4qq2-5wrp.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - osvgo",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-5864.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; nvd; osv; osvgo",
                    "url": "https://github.com/edgelesssys/contrast/security/advisories/GHSA-3ccm-4qq2-5wrp"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; nvd; osv",
                    "url": "https://www.vulncheck.com/advisories/edgeless-systems-contrast-through-1.20.0-denial-of-service-via-ciphertextcontainer"
                },
                {
                    "category": "external",
                    "summary": "Reference - osv; osvgo",
                    "url": "https://github.com/edgelesssys/contrast/commit/d6584fbff816037472034f7ad6e08cdbab1d870d"
                },
                {
                    "category": "external",
                    "summary": "Reference - osv; osvgo",
                    "url": "https://github.com/edgelesssys/contrast/releases/tag/v1.21.0"
                },
                {
                    "category": "external",
                    "summary": "Reference - osv",
                    "url": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/100xxx/CVE-2026-100836.json"
                },
                {
                    "category": "external",
                    "summary": "Reference - osv",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-100836"
                }
            ],
            "scores": [
                {
                    "cvss_v3": {
                        "version": "3.1",
                        "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L",
                        "baseScore": 4.3,
                        "baseSeverity": "MEDIUM"
                    },
                    "products": [
                        "CSAFPID-9474607",
                        "CSAFPID-9475361",
                        "CSAFPID-9478892"
                    ]
                }
            ],
            "title": "CVE-2026-100836"
        }
    ]
}