Summary
The /api/search/cve endpoint returns 500 Internal Server Error when the result set contains CVEs whose NVD configurations array includes an entry without a nodes field.
FastCVE's Config Pydantic model currently requires nodes to always be present:
class Config(BaseModel):
class Config:
extra = Extra.forbid
operator: Optional[Operator] = None
negate: Optional[bool] = None
nodes: List[Node]
When such a CVE is included in a sufficiently large API response, FastAPI response-model validation rejects the entire response.
Environment
- FastCVE API endpoint:
/api/search/cve
- Query period:
2026-07-11 through 2026-08-12
vulnerable=true
page-size=3000
Steps to reproduce
Run the following query:
curl --get 'http://127.0.0.1:8000/api/search/cve' \
--data-urlencode 'pub-start-date=2026-07-11' \
--data-urlencode 'pub-end-date=2026-08-12' \
--data-urlencode 'vulnerable=true' \
--data-urlencode 'page-idx=0' \
--data-urlencode 'page-size=3000'
Actual result:
HTTP 500
Internal Server Error
The FastCVE container logs show FastAPI response validation failing for two results:
INFO: 172.18.0.16:52224 - "GET /api/search/cve?pub-start-date=2026-07-11&pub-end-date=2026-08-12&vulnerable=true&page-idx=0&page-size=3000 HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
pydantic.error_wrappers.ValidationError: 2 validation errors for CveOutput
response -> result -> 1637 -> configurations -> 0 -> nodes
field required (type=value_error.missing)
response -> result -> 1638 -> configurations -> 0 -> nodes
field required (type=value_error.missing)
Root cause
FastCVE's Config model requires every configuration object to contain a nodes array:
class Config(BaseModel):
class Config:
extra = Extra.forbid
operator: Optional[Operator] = None
negate: Optional[bool] = None
nodes: List[Node]
However, the stored NVD data for at least two CVEs in this result set contains a configuration object where nodes is absent.
The affected response entries are:
result[1637].configurations[0]
result[1638].configurations[0]
Because nodes is defined as a mandatory field, FastAPI rejects the complete CveOutput response during serialization:
response -> result -> 1637 -> configurations -> 0 -> nodes
field required
response -> result -> 1638 -> configurations -> 0 -> nodes
field required
This means one CVE with a slightly different NVD configuration structure can cause an otherwise valid search containing thousands of CVEs to return HTTP 500.
Expected behavior
The API should return the CVE search results even when an NVD configuration entry does not contain a nodes field.
A missing nodes property should either:
- be represented as an empty list, or
- be accepted as an optional field
rather than causing response validation for the entire search result to fail.
Suggested fix
Preferably give nodes an empty-list default:
from pydantic import Field
class Config(BaseModel):
class Config:
extra = Extra.forbid
operator: Optional[Operator] = None
negate: Optional[bool] = None
nodes: List[Node] = Field(default_factory=list)
Alternatively, make the property optional:
class Config(BaseModel):
class Config:
extra = Extra.forbid
operator: Optional[Operator] = None
negate: Optional[bool] = None
nodes: Optional[List[Node]] = None
Using Field(default_factory=list) may be preferable because consumers of the API can continue treating nodes consistently as an iterable array:
instead of having to handle both arrays and null.
Additional consideration
The NVD CVE schema can evolve or contain records with optional structures that differ from FastCVE's generated Pydantic models.
Strict response validation of externally sourced NVD structures means a single unexpected or omitted property can currently cause the complete /api/search/cve response to fail.
Making optional NVD collection fields tolerant of missing values would make the API more resilient to schema variations and future NVD changes.
Summary
The
/api/search/cveendpoint returns500 Internal Server Errorwhen the result set contains CVEs whose NVDconfigurationsarray includes an entry without anodesfield.FastCVE's
ConfigPydantic model currently requiresnodesto always be present:When such a CVE is included in a sufficiently large API response, FastAPI response-model validation rejects the entire response.
Environment
/api/search/cve2026-07-11through2026-08-12vulnerable=truepage-size=3000Steps to reproduce
Run the following query:
Actual result:
The FastCVE container logs show FastAPI response validation failing for two results:
Root cause
FastCVE's
Configmodel requires every configuration object to contain anodesarray:However, the stored NVD data for at least two CVEs in this result set contains a configuration object where
nodesis absent.The affected response entries are:
Because
nodesis defined as a mandatory field, FastAPI rejects the completeCveOutputresponse during serialization:This means one CVE with a slightly different NVD configuration structure can cause an otherwise valid search containing thousands of CVEs to return HTTP 500.
Expected behavior
The API should return the CVE search results even when an NVD configuration entry does not contain a
nodesfield.A missing
nodesproperty should either:rather than causing response validation for the entire search result to fail.
Suggested fix
Preferably give
nodesan empty-list default:Alternatively, make the property optional:
Using
Field(default_factory=list)may be preferable because consumers of the API can continue treatingnodesconsistently as an iterable array:{ "nodes": [] }instead of having to handle both arrays and
null.Additional consideration
The NVD CVE schema can evolve or contain records with optional structures that differ from FastCVE's generated Pydantic models.
Strict response validation of externally sourced NVD structures means a single unexpected or omitted property can currently cause the complete
/api/search/cveresponse to fail.Making optional NVD collection fields tolerant of missing values would make the API more resilient to schema variations and future NVD changes.