---
id: "CVE-2026-100353"
page: "https://infrastack.ai/live/CVE-2026-100353"
kind: "vulnerability"
aliases: ["CVE-2026-100353", "GHSA-vrcc-3ch7-hppw", "GO-2026-6800"]
title: "kin-openapi: Incomplete Fix for GHSA-p6wj-qrr4-pgh5: Three Unpatched nil-Items Panic Paths in openapi3filter"
severity: "high"
cvss: 7.5
epss: 0.00335
exploited: false
status: "open"
category: "package"
products: [{"name": "github.com/getkin/kin-openapi", "fixed": ["0.149.0"], "affected": ">= 0.136.0, < 0.149.0", "ecosystem": "go"}]
ecosystems: ["go"]
tags: ["api-validation", "cwe-476", "go", "kin-openapi", "openapi", "package"]
not_affected_if: ["openapi3filter-unused", "version-outside-range"]
published_at: "2026-10-15T17:17:07+00:00"
first_seen_at: "2026-11-06T00:09:05+00:00"
updated_at: "2026-11-06T00:19:08+00:00"
sources: [{"source": "govuln", "url": "https://pkg.go.dev/vuln/GO-2026-6800", "first_seen_at": "2026-11-06T00:09:05+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-100353", "first_seen_at": "2026-11-06T00:19:01+00:00"}, {"source": "ghsa", "url": "https://github.com/advisories/GHSA-vrcc-3ch7-hppw", "first_seen_at": "2026-11-06T00:19:08+00:00"}]
exploit_sources: [{"type": "epss", "score": 0.00335, "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-100353"}]
---

# kin-openapi: Incomplete Fix for GHSA-p6wj-qrr4-pgh5: Three Unpatched nil-Items Panic Paths in openapi3filter

Link for people: https://infrastack.ai/live/CVE-2026-100353 (this .md is for agents)

kin-openapi is a Go library for validating requests against OpenAPI specs. Three code paths in its openapi3filter package panic on nil items, and an earlier fix for the same class of panic was incomplete.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- go:github.com/getkin/kin-openapi affected >= 0.136.0, < 0.149.0 fixed 0.149.0

## How to check

- Run `go list -m github.com/getkin/kin-openapi` in the module and look for a version from `0.136.0` up to, but not including, `0.149.0`.
- Check go.sum for `github.com/getkin/kin-openapi` at those versions.

## Fix

- `github.com/getkin/kin-openapi` moves to `0.149.0`.

## Timeline

- 2026-11-06T00:09:05+00:00 govuln https://pkg.go.dev/vuln/GO-2026-6800
- 2026-11-06T00:19:01+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-100353
- 2026-11-06T00:19:08+00:00 ghsa https://github.com/advisories/GHSA-vrcc-3ch7-hppw

## Documents

- [advisory] Vendor advisory: github.com https://github.com/getkin/kin-openapi/security/advisories/GHSA-vrcc-3ch7-hppw
- [advisory] Maintainer's advisory: api.github.com https://api.github.com/repos/getkin/kin-openapi/security-advisories/GHSA-vrcc-3ch7-hppw
- [fix] Patch: github.com https://github.com/getkin/kin-openapi/commit/9814d1f2b212f3508bf52296aa9e248b2122a5a9
- [fix] Release notes: github.com https://github.com/getkin/kin-openapi/releases/tag/v0.149.0

## From the sources

## 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
poc2: Returned normally, err = parameter "filter" in query has an error: path tags: array items schema is required
poc3: Returned normally, err = <nil>   (no panic; the allOf property is skipped by the decoder)
```

This confirms `urlValuesDecoder.parseArray` is the shared root cause for Paths 1 and 3, and `buildResObj` for Path 2.

## Impact

An unauthenticated client can trigger a deterministic nil-pointer panic in request validation with a single crafted request, against any application that validates OAS 3.1 requests with `openapi3filter` where a spec declares an array without `items`.

The severity depends on the host:

| Deployment | Behavior | Availability impact |
|------------|----------|---------------------|
| Standard `net/http` server (validation runs in the handler goroutine) | `net/http` recovers the panic per-connection; the connection is dropped and the process survives | Per-request denial of service (A:L) |
| Non-`net/http` hosts (e.g. fasthttp/connect adapters) or validation performed in an application-spawned goroutine | The panic is not recovered; the process crashes | Full-process denial of service (A:H) |

This was verified in both configurations: under a live `net/http` server the process survived (the panic was logged as `http: panic serving ...` and the process exited 0 at end of test), while the direct-call PoCs above crashed the process with `exit status 2`.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
