GHSA-RJ39-CV6W-8WV7
Vulnerability from github – Published: 2026-10-15 20:20 – Updated: 2026-10-15 20:20Summary
kin-openapi guards against NaN and Inf values in its built-in schema visitor (visitJSON) by returning ErrSchemaInputNaN / ErrSchemaInputInf when a float64 input violates those constraints. For OAS 3.1 specs, however, Schema.VisitJSON routes through useJSONSchema2020, which hands the value directly to santhosh-tekuri/jsonschema/v6 v6.0.2 without applying the same guard.
Inside jsonschema/v6 v6.0.2, numValidate builds a *big.Rat from the input via big.Rat.SetString(fmt.Sprintf("%v", v)). For NaN/Inf this parse fails silently and returns nil. numValidate then dereferences the nil *big.Rat (in math/big.(*Rat).Cmp), producing a Go runtime panic.
An attacker delivers this by sending an HTTP request with Content-Type: application/yaml (or application/x-yaml) and a YAML body containing .nan, .inf, or -.inf. The YamlBodyDecoder decodes those tokens into math.NaN() / math.Inf(±1) (standard YAML 1.2 behavior), and they propagate to the unguarded useJSONSchema2020 path whenever the schema declares a numeric constraint (minimum, maximum, exclusiveMinimum, exclusiveMaximum, or multipleOf).
Details
Root Cause
The built-in visitor visitJSON at openapi3/schema.go:1968 guards NaN/Inf explicitly:
case float64:
if math.IsNaN(value) {
return ErrSchemaInputNaN
}
if math.IsInf(value, 0) {
return ErrSchemaInputInf
}
For OAS 3.1 specs, VisitJSON dispatches to useJSONSchema2020 (openapi3/schema_jsonschema_validator.go:204), which contains no such guard:
func (schema *Schema) useJSONSchema2020(settings *schemaValidationSettings, value any) error {
validator, err := newJSONSchemaValidator(schema)
if err != nil {
return schema.visitJSON(settings, value)
}
return validator.validate(value) // value handed straight through
}
jsonSchemaValidator.validate calls jsonschema/v6.Schema.Validate (line 146), which reaches numValidate in v6.0.2. There, big.Rat.SetString(fmt.Sprintf("%v", v)) returns (nil, false) for NaN/Inf, and the code dereferences the nil *big.Rat in Rat.Cmp, causing the panic.
Proof of Concept
Environment
- kin-openapi v0.144.0 (tag
v0.144.0, commitf0407d5) - santhosh-tekuri/jsonschema/v6 v6.0.2 (transitive dep)
- Go 1.26.7
Spec
Minimal OAS 3.1 spec (spec.yaml) declaring a YAML body with a numeric constraint:
openapi: '3.1.0'
info: { title: Test, version: '1.0' }
paths:
/test:
post:
requestBody:
required: true
content:
application/yaml:
schema:
type: number
minimum: 0
responses:
'200': { description: OK }
Trigger
A single POST /test with Content-Type: application/yaml and body .nan, .inf, or -.inf. All three variants panic:
=== RUN TestNaNInf
[nan] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference
[inf] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference
[neginf] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference
Panic stack trace (confirms exact chain)
panic: runtime error: invalid memory address or nil pointer dereference
math/big.(*Rat).Cmp(0x0, ...) <- nil *big.Rat dereferenced
C:/Program Files/Go/src/math/big/rat.go:492
github.com/santhosh-tekuri/jsonschema/v6.(*validator).numValidate(...)
.../jsonschema/v6@v6.0.2/validator.go:525
github.com/santhosh-tekuri/jsonschema/v6.(*validator).validate(...)
.../jsonschema/v6@v6.0.2/validator.go:168
github.com/santhosh-tekuri/jsonschema/v6.(*Schema).validate(...)
.../jsonschema/v6@v6.0.2/validator.go:34
github.com/getkin/kin-openapi/openapi3.(*jsonSchemaValidator).validate(...)
openapi3/schema_jsonschema_validator.go:146
github.com/getkin/kin-openapi/openapi3.(*Schema).useJSONSchema2020(...) <- MISSING NaN/Inf guard
openapi3/schema_jsonschema_validator.go:211
github.com/getkin/kin-openapi/openapi3.(*Schema).VisitJSON(...)
openapi3/schema.go:1946
github.com/getkin/kin-openapi/openapi3filter.ValidateRequestBody(...)
openapi3filter/validate_request.go:364
github.com/getkin/kin-openapi/openapi3filter.ValidateRequest(...)
openapi3filter/validate_request.go:96
net/http behavior (severity nuance)
Behind a standard net/http server, the panic is recovered per-connection. The client sees a dropped connection; the server process continues:
Sending POST /test body=.nan against real net/http server...
2026/08/25 http: panic serving 127.0.0.1:40625: runtime error: invalid memory address or nil pointer dereference
CLIENT ERROR (connection dropped): Post ".../test": EOF
Process still alive after request: true
This is a recoverable panic, unlike the recursion finding. recover() catches it (verified by capturing the panic value in a defer in the same goroutine). Non-net/http hosts or validation performed in an application-spawned goroutine are not covered by that recovery and would experience a full-process crash.
Fix verification
Upgrading only the transitive dependency to jsonschema/v6@v6.0.3 (via go get github.com/santhosh-tekuri/jsonschema/v6@v6.0.3) eliminates the panic entirely; all three payloads return a clean validation error:
[nan] Returned normally, err = request body has an error: doesn't match schema: validation failed due to: at '': invalid jsonType float64
[inf] Returned normally, err = request body has an error: doesn't match schema: validation failed due to: at '': invalid jsonType float64
[neginf] Returned normally, err = request body has an error: doesn't match schema: validation failed due to: at '': invalid jsonType float64
This confirms the upstream jsonschema/v6 v6.0.3 release treats the NaN/Inf case as a bug and fixes it at the source. It also confirms useJSONSchema2020 is the reachable path: patching only the transitive dep removes the panic without touching kin-openapi code.
Why This Is a Vulnerability, Not by Design
- The library explicitly refuses NaN/Inf in its own visitor (
ErrSchemaInputNaN/ErrSchemaInputInfatschema.go:1968). The stated policy is: these values are not allowed. - The OAS 3.1 dispatch (
useJSONSchema2020) simply omits the same guard — a coding gap, not a design decision. - Upstream
jsonschema/v6v6.0.3 fixes the same case as a bug. Two independent code owners agree it should not panic. - The trigger is a single HTTP request body an unauthenticated client can send. There is no legitimate content-authoring reason to submit
.nan/.infas a numeric field.
Impact
- Per-request denial of service (net/http hosts). Every crafted request kills its own connection with zero attacker cost. Sustained flooding degrades service reliability and log noise.
- Full-process denial of service (non-net/http hosts or goroutine-spawned validation). No
net/httprecovery wrapper is present; the whole process crashes on a single request. - Attack surface is any OAS 3.1 API that accepts YAML bodies with numeric constraints. These constraints (
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf) are common on any numeric field with a range.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/getkin/kin-openapi"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.148.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-100352"
],
"database_specific": {
"cwe_ids": [
"CWE-754"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-15T20:20:27Z",
"nvd_published_at": "2026-10-15T16:17:31Z",
"severity": "HIGH"
},
"details": "## Summary\n\nkin-openapi guards against `NaN` and `Inf` values in its built-in schema visitor (`visitJSON`) by returning `ErrSchemaInputNaN` / `ErrSchemaInputInf` when a `float64` input violates those constraints. For OAS 3.1 specs, however, `Schema.VisitJSON` routes through `useJSONSchema2020`, which hands the value directly to `santhosh-tekuri/jsonschema/v6` v6.0.2 without applying the same guard.\n\nInside `jsonschema/v6` v6.0.2, `numValidate` builds a `*big.Rat` from the input via `big.Rat.SetString(fmt.Sprintf(\"%v\", v))`. For `NaN`/`Inf` this parse fails silently and returns `nil`. `numValidate` then dereferences the nil `*big.Rat` (in `math/big.(*Rat).Cmp`), producing a Go runtime panic.\n\nAn attacker delivers this by sending an HTTP request with `Content-Type: application/yaml` (or `application/x-yaml`) and a YAML body containing `.nan`, `.inf`, or `-.inf`. The `YamlBodyDecoder` decodes those tokens into `math.NaN()` / `math.Inf(\u00b11)` (standard YAML 1.2 behavior), and they propagate to the unguarded `useJSONSchema2020` path whenever the schema declares a numeric constraint (`minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, or `multipleOf`).\n\n## Details\n### Root Cause\n\nThe built-in visitor `visitJSON` at `openapi3/schema.go:1968` guards NaN/Inf explicitly:\n\n```go\ncase float64:\n if math.IsNaN(value) {\n return ErrSchemaInputNaN\n }\n if math.IsInf(value, 0) {\n return ErrSchemaInputInf\n }\n```\n\nFor OAS 3.1 specs, `VisitJSON` dispatches to `useJSONSchema2020` (`openapi3/schema_jsonschema_validator.go:204`), which contains no such guard:\n\n```go\nfunc (schema *Schema) useJSONSchema2020(settings *schemaValidationSettings, value any) error {\n validator, err := newJSONSchemaValidator(schema)\n if err != nil {\n return schema.visitJSON(settings, value)\n }\n return validator.validate(value) // value handed straight through\n}\n```\n\n`jsonSchemaValidator.validate` calls `jsonschema/v6.Schema.Validate` (line 146), which reaches `numValidate` in v6.0.2. There, `big.Rat.SetString(fmt.Sprintf(\"%v\", v))` returns `(nil, false)` for `NaN`/`Inf`, and the code dereferences the `nil` `*big.Rat` in `Rat.Cmp`, causing the panic.\n\n## Proof of Concept\n\n### Environment\n\n- kin-openapi v0.144.0 (tag `v0.144.0`, commit `f0407d5`)\n- santhosh-tekuri/jsonschema/v6 v6.0.2 (transitive dep)\n- Go 1.26.7\n\n### Spec\n\nMinimal OAS 3.1 spec (`spec.yaml`) declaring a YAML body with a numeric constraint:\n\n```yaml\nopenapi: \u00273.1.0\u0027\ninfo: { title: Test, version: \u00271.0\u0027 }\npaths:\n /test:\n post:\n requestBody:\n required: true\n content:\n application/yaml:\n schema:\n type: number\n minimum: 0\n responses:\n \u0027200\u0027: { description: OK }\n```\n\n### Trigger\n\nA single `POST /test` with `Content-Type: application/yaml` and body `.nan`, `.inf`, or `-.inf`. All three variants panic:\n\n```\n=== RUN TestNaNInf\n[nan] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference\n[inf] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference\n[neginf] PANIC (confirms vuln): runtime error: invalid memory address or nil pointer dereference\n```\n\n### Panic stack trace (confirms exact chain)\n\n```\npanic: runtime error: invalid memory address or nil pointer dereference\n\nmath/big.(*Rat).Cmp(0x0, ...) \u003c- nil *big.Rat dereferenced\n C:/Program Files/Go/src/math/big/rat.go:492\ngithub.com/santhosh-tekuri/jsonschema/v6.(*validator).numValidate(...)\n .../jsonschema/v6@v6.0.2/validator.go:525\ngithub.com/santhosh-tekuri/jsonschema/v6.(*validator).validate(...)\n .../jsonschema/v6@v6.0.2/validator.go:168\ngithub.com/santhosh-tekuri/jsonschema/v6.(*Schema).validate(...)\n .../jsonschema/v6@v6.0.2/validator.go:34\ngithub.com/getkin/kin-openapi/openapi3.(*jsonSchemaValidator).validate(...)\n openapi3/schema_jsonschema_validator.go:146\ngithub.com/getkin/kin-openapi/openapi3.(*Schema).useJSONSchema2020(...) \u003c- MISSING NaN/Inf guard\n openapi3/schema_jsonschema_validator.go:211\ngithub.com/getkin/kin-openapi/openapi3.(*Schema).VisitJSON(...)\n openapi3/schema.go:1946\ngithub.com/getkin/kin-openapi/openapi3filter.ValidateRequestBody(...)\n openapi3filter/validate_request.go:364\ngithub.com/getkin/kin-openapi/openapi3filter.ValidateRequest(...)\n openapi3filter/validate_request.go:96\n```\n\n### net/http behavior (severity nuance)\n\nBehind a standard `net/http` server, the panic is recovered per-connection. The client sees a dropped connection; the server process continues:\n\n```\nSending POST /test body=.nan against real net/http server...\n2026/08/25 http: panic serving 127.0.0.1:40625: runtime error: invalid memory address or nil pointer dereference\nCLIENT ERROR (connection dropped): Post \".../test\": EOF\nProcess still alive after request: true\n```\n\nThis is a **recoverable panic**, unlike the recursion finding. `recover()` catches it (verified by capturing the panic value in a `defer` in the same goroutine). Non-`net/http` hosts or validation performed in an application-spawned goroutine are not covered by that recovery and would experience a full-process crash.\n\n### Fix verification\n\nUpgrading only the transitive dependency to `jsonschema/v6@v6.0.3` (via `go get github.com/santhosh-tekuri/jsonschema/v6@v6.0.3`) eliminates the panic entirely; all three payloads return a clean validation error:\n\n```\n[nan] Returned normally, err = request body has an error: doesn\u0027t match schema: validation failed due to: at \u0027\u0027: invalid jsonType float64\n[inf] Returned normally, err = request body has an error: doesn\u0027t match schema: validation failed due to: at \u0027\u0027: invalid jsonType float64\n[neginf] Returned normally, err = request body has an error: doesn\u0027t match schema: validation failed due to: at \u0027\u0027: invalid jsonType float64\n```\n\nThis confirms the upstream `jsonschema/v6` v6.0.3 release treats the NaN/Inf case as a bug and fixes it at the source. It also confirms `useJSONSchema2020` is the reachable path: patching only the transitive dep removes the panic without touching kin-openapi code.\n\n## Why This Is a Vulnerability, Not by Design\n\n- The library explicitly refuses NaN/Inf in its own visitor (`ErrSchemaInputNaN` / `ErrSchemaInputInf` at `schema.go:1968`). The stated policy is: these values are not allowed.\n- The OAS 3.1 dispatch (`useJSONSchema2020`) simply omits the same guard \u2014 a coding gap, not a design decision.\n- Upstream `jsonschema/v6` v6.0.3 fixes the same case as a bug. Two independent code owners agree it should not panic.\n- The trigger is a single HTTP request body an unauthenticated client can send. There is no legitimate content-authoring reason to submit `.nan` / `.inf` as a numeric field.\n\n## Impact\n\n- **Per-request denial of service (net/http hosts).** Every crafted request kills its own connection with zero attacker cost. Sustained flooding degrades service reliability and log noise.\n- **Full-process denial of service (non-net/http hosts or goroutine-spawned validation).** No `net/http` recovery wrapper is present; the whole process crashes on a single request.\n- **Attack surface is any OAS 3.1 API that accepts YAML bodies with numeric constraints.** These constraints (`minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`) are common on any numeric field with a range.",
"id": "GHSA-rj39-cv6w-8wv7",
"modified": "2026-10-15T20:20:27Z",
"published": "2026-10-15T20:20:27Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/getkin/kin-openapi/security/advisories/GHSA-rj39-cv6w-8wv7"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-100352"
},
{
"type": "WEB",
"url": "https://github.com/getkin/kin-openapi/commit/4487f198ab8be0c37d6ca72c54f5dca4dc25270e"
},
{
"type": "PACKAGE",
"url": "https://github.com/getkin/kin-openapi"
},
{
"type": "WEB",
"url": "https://github.com/getkin/kin-openapi/releases/tag/v0.148.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "kin-openapi: YAML NaN/Inf Values Bypass Built-in Guards and Panic via OAS 3.1 Validation Path"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.