Skip to content

Harden Search Semantics, Request Lifecycles, and OpenSearch Readiness - #115

Merged
jdaigneau5 merged 5 commits into
devfrom
af/0.3.0-review
Aug 3, 2026
Merged

jdaigneau5 merged 5 commits into
devfrom
af/0.3.0-review

Conversation

@afoote-mitre

@afoote-mitre afoote-mitre commented Jul 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR hardens the Search API across CPE applicability, request validation, input limits, cancellation, and OpenSearch readiness.

Changes

CPE Applicability and Version Ranges

  • Correlates isVulnerable with the same CPE Match Criteria entry that matched the requested CPE.
  • Includes vulnerability metadata during candidate retrieval.
  • Validates that version-start bounds precede version-end bounds.
  • Allows equal bounds only when both bounds are inclusive.
  • Aligns query construction, semantic post-filtering, validation, and documentation.

Primary files:

  • utils/cpe.js
  • utils/searchQueryBuilder.js
  • controllers/middleware.js
  • controllers/searchController.js

Search Request and Error Handling

  • Enforces the POST /search JSON-body contract.
  • Rejects query-string parameters, unsupported fields, invalid media types, unsupported charsets, and malformed JSON.
  • Sanitizes upstream OpenSearch errors.
  • Returns retryable 503 responses with Retry-After when OpenSearch is unavailable.

Primary files:

  • server.js
  • routes/index.js
  • controllers/middleware.js
  • controllers/searchController.js
  • utils/errors.js

Input Complexity Limits

  • Adds limits for keyword length and term count.
  • Bounds the number and size of cveIds.
  • Limits CPE, source identifier, CVSS vector, and version-bound lengths.
  • Rejects oversized or overly complex requests before contacting OpenSearch.

Primary files:

  • controllers/middleware.js
  • utils/constants.js
  • utils/errors.js

Search Cancellation and Resource Management

  • Cancels OpenSearch requests when deadlines expire or clients disconnect.
  • Prevents page retrieval and response processing after cancellation.
  • Adds reference-counted tracking for shared in-flight searches.
  • Preserves shared work while active consumers remain and cancels it after the final consumer disconnects.
  • Removes abandoned CPE post-filter work from the queue.
  • Adds operation-level timing and cancellation metrics.

Primary files:

  • controllers/searchController.js
  • utils/searchDeadline.js
  • utils/searchInFlightRegistry.js
  • utils/searchPostFilterWorkQueue.js
  • utils/searchProvider.js
  • utils/searchPerformance.js

OpenSearch Readiness

  • Keeps /api/health-check as a lightweight process-liveness check.
  • Adds /api/ready-check for OpenSearch connectivity, index availability, and search permissions.
  • Uses a bounded, zero-result query for readiness validation.
  • Cancels readiness checks that exceed their timeout.
  • Returns a sanitized 503 SEARCH_NOT_READY response with Retry-After.
  • Validates the required cve-core SearchReader contract during initialization.

Primary files:

  • routes/index.js
  • utils/searchProvider.js
  • utils/requestLogging.js
  • config/default.jsonc
  • config/custom-environment-variables.jsonc

Documentation

  • Updates the README and OpenAPI specification for request limits, version-range rules, readiness behavior, cancellation, and configuration.
  • Documents the SearchReadinessTimeoutMs setting.

Primary files:

  • README.md
  • api-docs/openapi.json
  • .env.example

Deferred Items

CPE Applicability Candidate Limit

CPE searches that require semantic applicability filtering currently retrieve at most 10,000 lightweight candidate records from OpenSearch. The API then evaluates CPE criteria, version ranges, and vulnerability flags in Node.js before fetching the requested page.

If more than 10,000 records satisfy the initial OpenSearch query, valid matches outside that candidate window can be omitted. Because total-hit tracking is disabled for this operation, the API cannot currently distinguish a complete candidate set from one truncated at the limit. An incomplete result could also be cached and returned as though it were complete.

Resolving this requires a team decision between:

  • Iterating through all candidates with PIT and search_after, which improves correctness but can increase latency and OpenSearch load.
  • Rejecting searches whose candidate set exceeds the limit, which avoids silent omissions but makes broad CPE searches fail explicitly.
  • Retaining the limit and documenting the possibility of incomplete results.

sourceIdentifier Production Mapping

The current query builder maps sourceIdentifier to containers.cna.source.discovery. That field may represent discovery provenance rather than the source identifier exposed by the public API contract.

The production OpenSearch mapping and representative indexed records must be verified before changing this field because this repository does not own the index mapping. If the current path is incorrect, source identifier searches may return no results or records based on the wrong property. If the field is mapped as analyzed text rather than a keyword, the required query type may also differ.

The production data owner should confirm the authoritative field path, mapping type, and expected values before this filter is changed.

Deprecated /webSearch Endpoint

/webSearch accepts caller-provided OpenSearch query syntax through query_string. It does not use the stricter field-level contract and complexity controls implemented for /search.

This creates a broader query-complexity and abuse surface while the endpoint remains enabled. The finding is deferred because /webSearch is scheduled for removal once consumers have migrated to /search. Until removal, it can be disabled through WebSearchEnabled=false where no remaining integration depends on it.

Vulnerabilities Inherited Through cve-core

The two high-severity npm audit results are both associated with the same transitive adm-zip advisory inherited through cve-core. The affected ZIP-generation functionality is not invoked by the Search API, and npm does not currently identify a compatible fix available within this repository.

Remediation requires an updated cve-core release that upgrades or replaces the dependency. This repository should consume that release when available, but it will not patch or override code owned by cve-core.

@afoote-mitre
afoote-mitre requested a review from jdaigneau5 July 28, 2026 14:29
@afoote-mitre afoote-mitre self-assigned this Jul 28, 2026
@jdaigneau5
jdaigneau5 merged commit 7e33edc into dev Aug 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants