kin-openapi: Incomplete Fix for GHSA-p6wj-qrr4-pgh5: Three Unpatched nil-Items Panic Paths in openapi3filter
CVE-2026-100353 · GHSA-vrcc-3ch7-hppw · published 15 Oct 2026
How serious is it
- Severity: high, CVSS score 7.5 out of 10.
- No exploit prediction (EPSS) score yet.
- Not on the CISA list of exploited vulnerabilities.
- No public exploit in Exploit-DB.
Is your app affected by CVE-2026-100353?
Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.
Who is affected
github.com/getkin/kin-openapi(Go) >= 0.136.0, < 0.149.0
How to check
- Run
go list -m github.com/getkin/kin-openapiin your project to see the installed version, including copies pulled in by other packages. - Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.
How to fix
Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
- Upgrade
github.com/getkin/kin-openapito 0.149.0 or later, commit the lockfile and redeploy. - If a vulnerable version was live, check your logs and rotate the secrets that server could read.
The advisory
## Summary
The fix for GHSA-p6wj-qrr4-pgh5 addressed a nil-pointer dereference that occurs when an OpenAPI 3.1 array schema omits the `items` keyword (which is legal under JSON Schema 2020-12). That fix patched three decoder paths: the standalone `parseArray` function, the top-level array check in `UrlencodedBodyDecoder`, and `MultipartBodyDecoder`.
Three additional crash paths were missed. All of them reach the unguarded `urlValuesDecoder.parseArray` method (`openapi3filter/req_resp_decoder.go:576`) or the unguarded array branch in `buildResObj` (line 1015):
1. **Query parameters** with `type: array` and no `items`.
2. **deepObject** query parameters containing an array property with no `items`.
3. **URL-encoded request bodies** where the array lives inside an `allOf` / `anyOf` / `oneOf` sub-schema. This path bypasses the guard added by the GHSA-p6wj-qrr4-pgh5 fix, because that guard only inspects top-level properties.
Each path is triggerable by an unauthenticated client and produces a deterministic nil-pointer panic during request validation.
## Details
### Root Cause
The three paths patched for GHSA-p6wj-qrr4-pgh5 each received a nil-`items` guard:
```go
// standalone parseArray (line 1143) -- GUARDED
func parseArray(raw []string, schemaRef *openapi3.SchemaRef) ([]any, error) {
if schemaRef.Value.Items == nil || schemaRef.Value.Items.Value == nil { ... }
// UrlencodedBodyDecoder top-level property loop (line 1441) -- GUARDED
if propSchema.Value.Items == nil || propSchema.Value.Items.Value == nil { ... }
// MultipartBodyDecoder (line 1587) -- GUARDED
if valueSchema.Value.Items == nil { ... }
```
But `urlValuesDecoder.parseArray` (line 576), which handles query-parameter and urlencoded-body array decoding, has **no** such guard:
```go
func (d *urlValuesDecoder) parseArray(raw []string, schemaRef *openapi3.SchemaRef) ([]any, error) {
var value []any
for i, v := range raw {
item, err := d.parseValue(v, schemaRef.Value.Items) // Items is nil -> panic in parseValue
```
`parseValue` immediately dereferences the schema it is handed:
```go
func (d *urlValuesDecoder) parseValue(v string, schema *openapi3.SchemaRef) (any, error) {
if len(schema.Value.AllOf) > 0 { // schema == nil here -> nil pointer dereference
```
For the deepObject path, `buildResObj` (line 1015) has the same gap. Its array branch recurses with `schema.Value.Items` (line 1028), which can be nil, and the recursive call dereferences it at line 1015:
```go
case schema.Value.Type.Is("array"):
// ...
for i := range arr {
r, err := buildResObj(params, mapKeys, strconv.Itoa(i), schema.Value.Items) // nil Items
```
For the allOf body path, `UrlencodedBodyDecoder` validates only top-level `schema.Value.Properties` (line 1429-1449). But `decodeSchemaConstructs` (line 1474) recursively walks `AllOf` / `AnyOf` / `OneOf` sub-schemas and calls `decodeProperty` on their properties, which never pass through the top-level guard and reach `urlValuesDecoder.parseArray`.
## Proof of Concept
### Environment
- kin-openapi v0.144.0 (cloned at tag `v0.144.0`, commit `f0407d5`)
- Go 1.26.7
- Each PoC calls `doc.Validate()` first to prove the spec is legal, then drives `openapi3filter.ValidateRequest` directly
### Path 1: Query parameter array without items
Spec (query param `ids` is `type: array`, no `items`), request `GET /test?ids=1&ids=2`:
```
Validate() ACCEPTED the spec (type: array with no items is legal under OAS 3.1)
Calling ValidateRequest directly (no net/http recover)...
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x20 ...]
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).parseValue(...)
req_resp_decoder.go:605
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).parseArray(...)
req_resp_decoder.go:580
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).DecodeArray(...)
req_resp_decoder.go:569
...
github.com/getkin/kin-openapi/openapi3filter.ValidateRequest(...)
validate_request.go:83
exit status 2
```
### Path 2: deepObject nested array without items
Spec (deepObject param `filter` with array property `tags`, no `items`), request `GET /test?filter[tags][0]=a`:
```
Validate() ACCEPTED the spec
Calling ValidateRequest directly...
panic: runtime error: invalid memory address or nil pointer dereference
github.com/getkin/kin-openapi/openapi3filter.buildResObj(...)
req_resp_decoder.go:1012
github.com/getkin/kin-openapi/openapi3filter.buildResObj(...) <- recursive call with nil Items
req_resp_decoder.go:1028
github.com/getkin/kin-openapi/openapi3filter.makeObject(...)
req_resp_decoder.go:947
...
exit status 2
```
### Path 3: URL-encoded body with array inside allOf (bypasses the existing fix)
Spec (urlencoded body, `allOf` sub-schema with array property `tags`, no `items`), request `POST /submit` body `tags=a&tags=b`:
```
Validate() ACCEPTED the spec
Calling ValidateRequest directly...
panic: runtime error: invalid memory address or nil pointer dereference
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).parseValue(...)
req_resp_decoder.go:605
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).parseArray(...)
req_resp_decoder.go:580
github.com/getkin/kin-openapi/openapi3filter.(*urlValuesDecoder).DecodeArray(...)
req_resp_decoder.go:569
...
github.com/getkin/kin-openapi/openapi3filter.decodeProperty(...) <- reached via decodeSchemaConstructs (allOf walker)
req_resp_decoder.go:1519
exit status 2
```
The `decodeProperty` frame confirms the array was reached by walking the `allOf` sub-schema, bypassing the top-level guard that the GHSA-p6wj-qrr4-pgh5 fix added.
### Fix verification
Adding a single nil-`items` guard to `urlValuesDecoder.parseArray` (plus one to the `buildResObj` array branch) turns all three panics into clean validation errors:
```
poc1: Returned normally, err = parameter "ids" in query has an error: array items schema is required for decoding
p…
Check your whole app
Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.
References
- github.com/getkin/kin-openapi/security/advisories/GHSA-vrcc-3ch7-hppw
- nvd.nist.gov/vuln/detail/CVE-2026-100353
- github.com/getkin/kin-openapi/commit/9814d1f2b212f3508bf52296aa9e248b2122a5a9
- github.com/getkin/kin-openapi/releases/tag/v0.149.0
- github.com/advisories/GHSA-vrcc-3ch7-hppw
Merged from GitHub Advisory Database. Last updated 23 Oct 2026. All vulnerabilities · RSS · JSON