CVE
CVE-2026-119028, CVE-2026-119027, CVE-2026-118764, CVE-2026-118664, CVE-2026-118763, CVE-2026-62374, CVE-2026-119051
CWE
CWE-94, CWE-400, CWE-407, CWE-522, CWE-347, CWE-770
Affected Surface
- Go module `github.com/oapi-codegen/oapi-codegen/v2` versions `>= 2.0.0, < 2.8.1` (`CVE-2026-119028` / `GHSA-xrqw-w576-xgj2`, CVSS 8.8) and `>= 2.5.0, < 2.8.1` (`CVE-2026-119027` / `GHSA-rjwr-m7qx-3fjr`, CVSS 7.5; plus `GHSA-g2vv-83pm-v2hc`)
- npm `minimatch` versions `< 11.0.1` (`CVE-2026-118764` / `GHSA-g3hv-75wg-m249`, CVSS v4.0 8.7 High, when `optimizationLevel >= 2`)
- npm `decode-uri-component` versions `<= 0.5.0` (`CVE-2026-118664` / `GHSA-qr28-fpjm-wq7f`, CVSS v4.0 8.2 High)
- npm `@sigstore/oci` versions `< 0.7.2` (`CVE-2026-118763` / `GHSA-j63v-mwhm-56jx`, CVSS 7.4 High)
- npm `@sd-jwt/core` and `@sd-jwt/decode` versions `<= 0.19.0` (`CVE-2026-62374` / `GHSA-f9j6-8p6x-r9j6`, CVSS v4.0 7.1 High)
- npm `flat` versions `<= 6.0.1` (`CVE-2026-119051`, CVSS v4.0 8.2 High / v3.1 5.9 Medium, unpatched upstream)
TL;DR
On 29 October 2026, NVD and the GitHub Advisory Database published seven advisories across foundational Go code generation and JavaScript/TypeScript packages:
- Go
oapi-codegen< 2.8.1(CVE-2026-119028, CVSS 8.8 High;CVE-2026-119027, CVSS 7.5 High; andGHSA-g2vv-83pm-v2hc): When generating Go client or server code from an OpenAPI specification,constants.tmplemitted non-stringenumvalues (integer,number,boolean) into aconst (...)block without quoting or validating that they were numeric/boolean literals (CVE-2026-119028), andserver-urls.tmplemittedservers[].x-go-name, server variable names, and undeclared{placeholder}names directly as Go identifiers (CVE-2026-119027). An untrusted or third-party OpenAPI spec could close theconstblock and inject afunc init() { ... }block that executes automatically when the generated Go package is built or tested. Version2.8.1(commit068f1bcd16) also fixes template injection via EchooperationIdmiddleware keys,toStringArraytrailing-backslash security scopes,x-go-type-importaliases, response status keys, and webhook/FiberContentTypestrings. minimatch< 11.0.1(CVE-2026-118764/GHSA-g3hv-75wg-m249, CVSS v4.0 8.7 High): AtoptimizationLevel: 2or higher,firstPhasePreProcess()split<pre>/**/../<p>/<rest>into<pre>/{..,**}/<p>/<rest>inside ado { ... } while (didSomething)loop without checkingbraceExpandMax, doubling the pattern array on each**/..segment, andsecondPhasePreProcess()compared every expanded pattern pairwise (O(n^2)). A 30-segment**/../a/bpattern expanded to2^30entries and hung the Node.js process. Fixed in11.0.1(11.0.3current).decode-uri-component<= 0.5.0(CVE-2026-118664/GHSA-qr28-fpjm-wq7f, CVSS v4.0 8.2 High): WhendecodeURIComponent()threw on a malformed tail (such as%zz), the fallbackcustomDecodeURIComponent()collected every distinct%XXsequence intoreplaceMapand raninput.replace(new RegExp(key, 'g'), replaceMap[key])across the entire string for each entry. Thirty-two thousand distinct percent-encoded runs plus a trailing%zzblocked the Node.js event loop for ~20 seconds. Fixed in0.5.1via single-pass linear decoding.@sigstore/oci< 0.7.2(CVE-2026-118763/GHSA-j63v-mwhm-56jx, CVSS 7.4 High):RegistryClient.signIn()attached registryAuthorizationand Docker config headers as defaults on the shared HTTP client, andRegistryClient.uploadBlob()issued a freshPUTto whatever absoluteLocationURL the registry returned fromPOST /v2/<repo>/blobs/uploads/without checking its origin or scheme. Because thePUTwas a new request rather than an HTTP redirect, redirect header-stripping never ran, leaking registry bearer tokens or Basic credentials to an attacker-chosen upload host. Fixed in@sigstore/oci@0.7.2.@sd-jwt/coreand@sd-jwt/decode<= 0.19.0(CVE-2026-62374/GHSA-f9j6-8p6x-r9j6, CVSS v4.0 7.1 High) andflat<= 6.0.1(CVE-2026-119051, CVSS v4.0 8.2 High):@sd-jwt/decodesilently dropped tampered or invalid-UTF-8 Selective Disclosure JWT disclosures whose digest did not match the Issuer-signed_sdarray instead of rejecting the presentation per RFC 9901 Section 7.1, allowing a holder to strip restrictive claims (age,role,restriction) while verification succeeded (fixed in@sd-jwt/core@0.20.0;@sd-jwt/decodestandalone remains unpatched). Inflat<= 6.0.1,unflatten()converts any bare numeric key (such as{"a.4294967294": 1}) into an array index without an upper bound, creating a 4.29-billion-element sparse array that locks up Node.js onJSON.stringifyor.forEach().
What to do now: Upgrade github.com/oapi-codegen/oapi-codegen/v2 to >= v2.8.1, minimatch to >= 11.0.1 (11.0.3 current), decode-uri-component to >= 0.5.1, @sigstore/oci to >= 0.7.2, and @sd-jwt/core to >= 0.20.0 (0.24.0 current, and remove direct imports of @sd-jwt/decode). For flat <= 6.0.1, pass { object: true } to unflatten() when handling untrusted keys.
Affected packages and projects
| Ecosystem | Package | CVE / GHSA | Severity | Affected versions | Fixed version | Vulnerable component |
|---|---|---|---|---|---|---|
| Go | github.com/oapi-codegen/oapi-codegen/v2 | CVE-2026-119028 (GHSA-xrqw-w576-xgj2), CVE-2026-119027 (GHSA-rjwr-m7qx-3fjr), GHSA-g2vv-83pm-v2hc | CVSS 8.8 / 7.5 High | >= 2.0.0, < 2.8.1 (119028); >= 2.5.0, < 2.8.1 (119027) | 2.8.1 | pkg/codegen/codegen.go (GenerateEnums), templates/constants.tmpl, templates/server-urls.tmpl, validate_spec.go |
| npm | minimatch | CVE-2026-118764 (GHSA-g3hv-75wg-m249) | CVSS v4.0 8.7 High | < 11.0.1 (optimizationLevel >= 2) | 11.0.1 (11.0.3 current) | src/index.ts (firstPhasePreProcess, secondPhasePreProcess) |
| npm | decode-uri-component | CVE-2026-118664 (GHSA-qr28-fpjm-wq7f) | CVSS v4.0 8.2 High | <= 0.5.0 | 0.5.1 | index.js (customDecodeURIComponent) |
| npm | @sigstore/oci | CVE-2026-118763 (GHSA-j63v-mwhm-56jx) | CVSS 7.4 High | < 0.7.2 | 0.7.2 | packages/oci/src/registry.ts (RegistryClient.signIn, uploadBlob), credentials.ts |
| npm | @sd-jwt/core, @sd-jwt/decode | CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) | CVSS v4.0 7.1 High | <= 0.19.0 | @sd-jwt/core 0.20.0 (0.24.0 current; @sd-jwt/decode unpatched) | packages/core/src/decode/decode.ts, packages/core/src/sdjwt.ts |
| npm | flat | CVE-2026-119051 | CVSS v4.0 8.2 High (v3.1 5.9 Medium) | <= 6.0.1 | None (pass { object: true } to unflatten()) | index.js (getkey, unflatten) |
Technical analysis
1. Go oapi-codegen 2.8.1 (CVE-2026-119028 and CVE-2026-119027): Go source injection via non-string enums, server-urls, and operationId
In oapi-codegen, pkg/codegen/templates/constants.tmpl renders enum constants for each schema that defines an enum array:
{{range $Enum := .EnumDefinitions}}
// Defines values for {{$Enum.TypeName}}.
const (
{{range $name, $value := $Enum.GetValues}}
{{$name}} {{$Enum.TypeName}} = {{if $Enum.ValueWrapper}}{{$value | toGoString}}{{else}}{{$value}}{{end -}}
{{end}}
)
For string enums, $Enum.ValueWrapper is " and $value is escaped via toGoString. For integer, number, and boolean schemas, $Enum.ValueWrapper is empty, so $value was interpolated raw into the Go source file (CVE-2026-119028 / GHSA-xrqw-w576-xgj2). Because OpenAPI YAML/JSON parsers allow arbitrary values inside an enum: list unless validated, a spec containing:
components:
schemas:
Count:
type: integer
enum:
- "1)\nfunc init() { /* arbitrary Go code */ }\nconst (_ Count = 2"
closed the const (...) block and emitted a top-level func init() that ran as soon as a developer or CI pipeline compiled or tested the package. Similarly, in pkg/codegen/templates/server-urls.tmpl (CVE-2026-119027 / GHSA-rjwr-m7qx-3fjr), const {{ .GoName }} = ... and func New{{ .GoName }}(...) emitted servers[].x-go-name, server variable names, and undeclared {placeholder} names without checking that they were valid Go identifiers.
Commit 068f1bcd16 (PR #2626, released in v2.8.1) hardens GenerateEnums() and adds ValidateServerURLs() and spec-wide escaping across seven additional template sinks:
--- a/pkg/codegen/codegen.go
+++ b/pkg/codegen/codegen.go
@@ -1533,6 +1537,19 @@ func GenerateEnums(t *template.Template, types []TypeDefinition) (string, error)
+ for _, e := range enums {
+ if e.ValueWrapper != "" {
+ continue
+ }
+ for _, value := range SortedMapKeys(e.Schema.EnumValues) {
+ if !isNumberOrBoolLiteral(e.Schema.EnumValues[value]) {
+ return "", fmt.Errorf("enum value %q of %s is not a number or boolean literal, which its Go type %s requires", e.Schema.EnumValues[value], e.TypeName, e.Schema.GoType)
+ }
+ }
+ }
The same commit also replaces options.OperationMiddlewares["{{.MiddlewareKey}}"] with {{.MiddlewareKey | toGoString}} in Echo v4/v5 templates, quotes each security scope with strconv.Quote in toStringArray() (fixing a trailing-backslash quote escape), validates x-go-type-import.name as a Go identifier, restricts response keys to ^(default|[1-5]XX|[1-9][0-9][0-9])$, and passes {{.ContentType | toGoString}} in webhook-initiator.tmpl, callback-initiator.tmpl, and strict-fiber-v3.tmpl.
2. minimatch 11.0.1 (CVE-2026-118764) and decode-uri-component 0.5.1 (CVE-2026-118664): exponential glob expansion and quadratic URI fallback
In minimatch (< 11.0.1), passing { optimizationLevel: 2 } activates firstPhasePreProcess() and secondPhasePreProcess() in src/index.ts. Whenever firstPhasePreProcess() encountered <pre>/**/../<p>/<rest>, it split the pattern into two branches (.. and **) and set didSomething = true, repeating the do { ... } while (didSomething) loop over the newly pushed branches without checking braceExpandMax. Thirty **/../a/b segments doubled globParts 30 times, and secondPhasePreProcess() then ran a nested O(n^2) deduplication loop over the expanded set. Commit 77a0f5c4b8 stops splitting **/.. once globParts.length >= braceExpandMax (default 100,000) and skips pairwise deduplication when globParts.length > 1000:
--- a/src/index.ts
+++ b/src/index.ts
@@ -1178,7 +1183,8 @@ export class Minimatch {
p === '..' ||
!p2 ||
p2 === '.' ||
- p2 === '..'
+ p2 === '..' ||
+ globParts.length >= braceExpandMax
) {
continue
}
@@ -1242,6 +1248,9 @@ export class Minimatch {
secondPhasePreProcess(globParts: string[][]): string[][] {
+ if (globParts.length > 1000) return globParts
for (let i = 0; i < globParts.length - 1; i++) {
In decode-uri-component (<= 0.5.0), decodeUriComponent(input) first tries decodeURIComponent(input) and falls back to customDecodeURIComponent(input) on URIError. Previously, customDecodeURIComponent() matched every percent-encoded run, stored its decoded value in replaceMap[match], and then iterated for (const key of Object.keys(replaceMap)) { input = input.replace(new RegExp(key, 'g'), replaceMap[key]); }. When a request body or query string contained 32,000 distinct valid runs (%00%00x%00%01x...) followed by a single invalid %zz at the end, the fallback compiled and executed 32,000 full-string regex replacements over a ~220 KB string (~20 seconds of synchronous CPU time). Commit fad01d65b9 (0.5.1) replaces the replaceMap regex loop with a single linear pass (decode(input)).
3. @sigstore/oci 0.7.2 (CVE-2026-118763) and @sd-jwt/core 0.20.0 (CVE-2026-62374)
In @sigstore/oci (< 0.7.2), RegistryClient.signIn() stored registry Authorization and custom Docker headers as default headers on the client instance, and RegistryClient.uploadBlob() initiated a blob upload (POST /v2/<repo>/blobs/uploads/) and then sent an explicit PUT request to the URL returned in the Location response header. In the OCI Distribution Spec, Location frequently points to a separate blob-storage host. Because uploadBlob() constructed a new PUT request to that Location URL rather than following an HTTP 307 redirect, redirect-level credential stripping never triggered, and the client sent the registry’s Authorization bearer token or Basic credentials straight to the external host. Commit b855f46cfe and commit e4ca65c3ab (@sigstore/oci@0.7.2) scope registry credential headers strictly to the registry origin, enforce exact-host Docker Hub alias matching (DOCKER_HUB_ALIASES.has(registry) instead of registry.endsWith('docker.io')), and block non-HTTPS or private-IP destinations unless --allow-private-origin (fetchOpts.allowedPrivateOrigins) is explicitly configured.
In @sd-jwt/core and @sd-jwt/decode (<= 0.19.0, CVE-2026-62374 / GHSA-f9j6-8p6x-r9j6), unpackObjInternal() and unpackArray() built a map[digest] = disclosure lookup table from the presented Disclosures and then walked the Issuer-signed _sd digest array. Any Disclosure in the presentation whose digest did not match an entry in _sd (because the holder tampered with the Disclosure or inserted invalid UTF-8 bytes that TextDecoder replaced with U+FFFD) simply went unused in map without raising an error, violating RFC 9901 Section 7.1 Step 5. If a verifier checked for a negative or constraining attribute (such as an age or role restriction) and defaulted to permitting access when that claim was absent, a holder could corrupt that single Disclosure to silently strip the claim while the Issuer signature and Key Binding JWT remained valid. Commit c7cf23dbc1 (@sd-jwt/core@0.20.0, PR #389) enforces strict base64url/UTF-8 JSON decoding (decodeBase64urlJsonStrict), rejects unreferenced and duplicate disclosure digests, and rejects bare JWTs lacking an SD-JWT ~ separator.
Detection and remediation
# 1. Check Go repositories for vulnerable oapi-codegen versions (< v2.8.1)
rg -n 'oapi-codegen' go.mod go.sum Makefile generate.go 2>/dev/null
go version -m $(which oapi-codegen 2>/dev/null) 2>/dev/null || true
# 2. Check Node.js dependency trees and lockfiles
npm ls minimatch decode-uri-component @sigstore/oci @sd-jwt/core @sd-jwt/decode flat 2>/dev/null || true
rg -n '"(minimatch|decode-uri-component|@sigstore/oci|@sd-jwt/(core|decode)|flat)"' \
package.json package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null
# 3. Search codebases for minimatch optimizationLevel >= 2 or flat unflatten() without { object: true }
rg -n '\b(optimizationLevel|unflatten)\b' --glob '*.{js,ts,mjs,cjs}' . 2>/dev/null
- Upgrade
oapi-codegento>= v2.8.1and regenerate any Go code produced from external or partner OpenAPI specifications:go get github.com/oapi-codegen/oapi-codegen/v2@v2.8.1 - Upgrade npm dependencies:
minimatch: upgrade to>= 11.0.1(11.0.3is latest).decode-uri-component: upgrade to>= 0.5.1.@sigstore/ociand@sigstore/cli: upgrade to@sigstore/oci >= 0.7.2. If you push attestations to a private HTTP registry, pass--allow-private-origin <scheme://host:port>.@sd-jwt/core: upgrade to>= 0.20.0(0.24.0is latest) and replace any direct usage of the standalone@sd-jwt/decodepackage with@sd-jwt/core.flat: when callingunflatten()on untrusted JSON keys, passunflatten(data, { object: true })or reject dotted segments containing integers larger than your expected array bound before callingunflatten().
Timeline
- 2026-07-18 to 2026-08-29: OpenWallet Foundation merges PR
#389(c7cf23dbc1) insd-jwt-js, shipping@sd-jwt/core@0.20.0. - 2026-08-04: Sigstore releases
@sigstore/oci@0.7.2with commitsb855f46cfeande4ca65c3ab. - 2026-10-23:
decode-uri-componentreleases0.5.1(fad01d65b9). - 2026-10-28:
oapi-codegenreleasesv2.8.1(068f1bcd16, PR#2626) andminimatchreleases11.0.1(77a0f5c4b8). - 2026-10-29 (
12:17to17:18 UTC): NVD and the GitHub Advisory Database publishCVE-2026-119027,CVE-2026-119028,CVE-2026-119051,CVE-2026-118664,CVE-2026-118763,CVE-2026-118764, andCVE-2026-62374.
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.
References
- oapi-codegen commit 068f1bcd16 (PR #2626: quote or validate every spec string that reaches generated Go source, v2.8.1)
- oapi-codegen advisories GHSA-xrqw-w576-xgj2 (CVE-2026-119028), GHSA-rjwr-m7qx-3fjr (CVE-2026-119027), and GHSA-g2vv-83pm-v2hc
- minimatch advisory GHSA-g3hv-75wg-m249 (CVE-2026-118764) and commit 77a0f5c4b8
- decode-uri-component advisory GHSA-qr28-fpjm-wq7f (CVE-2026-118664) and commit fad01d65b9
- sigstore-js advisory GHSA-j63v-mwhm-56jx (CVE-2026-118763) and commits b855f46cfe and e4ca65c3ab
- sd-jwt-js advisory GHSA-f9j6-8p6x-r9j6 (CVE-2026-62374) and commit c7cf23dbc1
- flat issue #195 (CVE-2026-119051: unbounded array allocation via numeric keys in unflatten)