Skip to content

NullReferenceException on boolean schema in components/schemas #2838

@pawlos

Description

@pawlos

Describe the bug
OpenApiDocument.Load throws NullReferenceException from Microsoft.OpenApi.OpenApiWorkspace.RegisterComponents when an OpenAPI 3.1 document contains a components/schemas entry whose value is a JSON boolean - e.g. "X": true.

The input is spec-valid. OpenAPI 3.1 §4.8.24 defines its Schema Object as "a superset of the JSON Schema Specification Draft 2020-12", and JSON Schema 2020-12 §4.3.2 "Boolean JSON Schemas" permits a schema to be the literal true (always validates) or false (never validates). The parser should either materialize a proper schema value for these entries or surface a structured diagnostic - not throw NullReferenceException.

Affected:

  • Microsoft.OpenApi 3.5.2 (latest release)
  • main at 78e17ca (2026-04-23) - still reproduces

OpenApi File To Reproduce
55-byte JSON file:

{"openapi":"3.1.0","components":{"schemas":{"X":true}}}

info is a required field per the OpenAPI spec, but the deserializer still reaches RegisterComponents without it, so it can be omitted from the minimal repro. Adding "info":{"title":"x","version":"1"} does not change the behavior.

Expected behavior
The parser should not throw NullReferenceException on a spec-valid OpenAPI 3.1 document. Either accepting the boolean schema or surfacing a structured diagnostic would be fine - how boolean schemas are represented in the object model is a design decision for the maintainers.

Screenshots/Code Snippets
Repro:

using Microsoft.OpenApi;
using Microsoft.OpenApi.Reader;

var bytes = "{\"openapi\":\"3.1.0\",\"components\":{\"schemas\":{\"X\":true}}}"u8.ToArray();
using var ms = new MemoryStream(bytes);
OpenApiDocument.Load(ms, format: null, new OpenApiReaderSettings());
// -> System.NullReferenceException at OpenApiWorkspace.RegisterComponents

Stack trace:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.OpenApi.OpenApiWorkspace.RegisterComponents(OpenApiDocument document)
       in src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs:line 96
   at Microsoft.OpenApi.Reader.V31.OpenApiV31Deserializer.LoadOpenApi(RootNode, Uri)
       in src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs:line 61
   at Microsoft.OpenApi.Reader.V31.OpenApiV31VersionService.LoadDocument(RootNode, Uri)
       in src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs:line 59
   at Microsoft.OpenApi.Reader.ParsingContext.Parse(JsonNode, Uri)
   at Microsoft.OpenApi.Reader.OpenApiJsonReader.Read(JsonNode, Uri, OpenApiReaderSettings)
   at Microsoft.OpenApi.Reader.OpenApiJsonReader.Read(MemoryStream, Uri, OpenApiReaderSettings)
   at Microsoft.OpenApi.Reader.OpenApiModelFactory.InternalLoad(MemoryStream, string, OpenApiReaderSettings)
   at Microsoft.OpenApi.Reader.OpenApiModelFactory.Load(MemoryStream, string, OpenApiReaderSettings)
   at Microsoft.OpenApi.OpenApiDocument.Load(MemoryStream, string, OpenApiReaderSettings)

When the schema deserializer encounters a bare boolean in place of a schema object, the resulting Components.Schemas dictionary contains an entry with a null value. The document?.Components == null guard at the top of RegisterComponents does not catch this; the per-entry dereference then throws.

The same loop shape exists for every other component map in this method - Parameters, Responses, RequestBodies, Links, Callbacks, Examples, Headers, SecuritySchemes, PathItems - and may be worth a consistency audit for the same null-value pattern.

Additional context

  • Runtime: .NET 10.0 SDK; purely managed code, reproduces on all platforms.
  • Discovery: coverage-guided fuzzing with AFL++ 4.00c + SharpFuzz 2.2.0 against Microsoft.OpenApi 3.5.2. The 55-byte repro above is minimized from a larger AFL-produced crash input.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions