Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Rename `.env.example` to `.env` and replace or check the following values.
- `SearchReadinessTimeoutMs` - optional timeout for the OpenSearch index readiness check, default `5000`
- `RequestLogSuccessSampleRate` - optional fraction of successful non-health-check access logs to retain, default `0.1`
- `RequestLogHealthChecks` - optional flag to retain successful health-check access logs, default `false`
- `WebSearchEnabled` - optional deprecated `/webSearch` feature flag, default `true`
- `WebSearchEnabled` - optional `/webSearch` availability flag, default `true`
- `NPM_CA_CERT` - optional absolute host path to a corporate or self-signed CA certificate bundle used only during local Docker Compose builds

```bash
Expand Down Expand Up @@ -80,7 +80,7 @@ The Search API will be served at `localhost:3000`.

`GET /api/health-check` is a process liveness check. It returns HTTP 200 when the Node.js process is running and deliberately does not contact OpenSearch. Use it where a dependency outage should not restart otherwise healthy API tasks.

`GET /api/ready-check` sends a minimal zero-result search to the configured CVE index. This verifies connectivity, index availability, and the same search permission used by the API without retrieving CVE records or counting all matches. It returns HTTP 200 when search requests can be served. Configuration errors, connection failures, timeouts, incompatible `cve-core` SearchReader contracts, and a missing index return a sanitized HTTP 503 `SEARCH_NOT_READY` response with `Retry-After: 5`. The OpenSearch request is limited to five seconds by default and can be changed with `SearchReadinessTimeoutMs`.
`GET /api/ready-check` first verifies that the configured CVE index exposes the field capabilities required by the `/search` contract, then sends a minimal zero-result search. This checks required mappings, connectivity, index availability, and the same search permission used by the API without retrieving CVE records or counting all matches. It returns HTTP 200 when search requests can be served. Configuration errors, connection failures, timeouts, incompatible `cve-core` SearchReader contracts, missing or incompatible field mappings, and a missing index return a sanitized HTTP 503 `SEARCH_NOT_READY` response with `Retry-After: 5`. Each OpenSearch readiness request is limited to five seconds by default and can be changed with `SearchReadinessTimeoutMs`.

An AWS load balancer can use `/api/ready-check` to stop routing search traffic to an unready task while the container orchestrator continues using `/api/health-check` for process liveness. Coordinate that probe selection with the infrastructure team before changing deployed health-check behavior.

Expand Down Expand Up @@ -212,7 +212,7 @@ Numeric segments used in version range comparisons ignore leading zeros. A store

Future recommendation: broad `virtualMatchString` values can be expensive because they may require large candidate scans plus semantic CPE post-filtering. Requiring concrete leading components, such as `part` and `vendor` for normal searches and `part`, `vendor`, and `product` for version range searches, would reduce the most expensive public search shapes. Narrowing the accepted searches should be handled as a policy decision before implementation.

`POST /webSearch` is deprecated in favor of `POST /search`. It remains enabled by default during consumer migration and can be disabled without a code change by setting `WebSearchEnabled=false` and restarting the service. When disabled, it returns HTTP `410` with the stable error code `WEB_SEARCH_DISABLED` before validating the request or contacting OpenSearch.
`POST /webSearch` is a supported raw-query endpoint. It is enabled by default and can be disabled without a code change by setting `WebSearchEnabled=false` and restarting the service. When disabled, it returns HTTP `410` with the stable error code `WEB_SEARCH_DISABLED` before validating the request or contacting OpenSearch.

While enabled, `POST /webSearch` requires a non-empty JSON `query` string. It also accepts optional `sort`, `from`, and `size` fields:

Expand All @@ -233,6 +233,8 @@ While enabled, `POST /webSearch` requires a non-empty JSON `query` string. It al
- `from` must be an integer greater than or equal to `0`
- `size` must be an integer from `1` to `500`

The controller validates successful `BasicSearchManager` responses before returning HTTP 200. A response without the expected status metadata, total-hit count, or hit array is treated as an invalid upstream response and returns a sanitized HTTP 502.

## Swagger API docs

Swagger API docs are regenerated by `npm run dev` and can be regenerated manually using:
Expand Down Expand Up @@ -274,10 +276,12 @@ Each `/search` request owns a lifecycle cancellation signal. When its overall de

### Semantic Post-Filtering

CVSS vector filters, SSVC filters, date-bounded positive `knownExploited` searches, `cpeName`, and `virtualMatchString` searches use semantic post-filtering where OpenSearch cannot guarantee the required same-entry or version-comparison behavior. These searches retrieve up to 10,000 lightweight candidates, apply semantic checks in Node.js, paginate the matching CVE IDs, and fetch the requested page as complete CVE records. Every token supplied to one CVSS vector filter must occur in the same eligible vector.
CVSS vector filters, SSVC filters, date-bounded positive `knownExploited` searches, `cpeName`, and `virtualMatchString` searches use semantic post-filtering where OpenSearch cannot guarantee the required same-entry or version-comparison behavior. These searches retrieve up to 10,000 lightweight candidates, apply semantic checks in Node.js, paginate the matching CVE IDs, and fetch the requested page as complete CVE records. Every slash-delimited token supplied to one CVSS vector filter must match a complete token in the same eligible vector; a base token such as `AV:N` does not match a modified token such as `MAV:N`.

The reported total and pagination are complete only within that bounded candidate set; qualifying records beyond the first 10,000 OpenSearch candidates may not be represented. This preserves the existing bounded post-filter behavior until PIT-based pagination is implemented. A `knownExploited` filter without date boundaries uses a direct OpenSearch query and retains ordinary exact-total behavior.

`/search` orders OpenSearch results by CVE ID so repeated shallow-page requests use a deterministic sort. The response `pageSize` is the number of records actually returned, including zero for an out-of-range page. A stable sort does not provide a point-in-time snapshot, so index updates between separate page requests can still shift results until PIT-based pagination is implemented.

The API does not cache, coalesce, queue, or rate-limit searches in process. Each request executes its own required OpenSearch operations. Public rate enforcement, admission control, shared caching, and performance telemetry must be supplied by the deployment infrastructure when those capabilities are enabled.

OpenSearch operations use one attempt and return a sanitized HTTP 504 `SEARCH_TIMEOUT` response when they exceed the 20-second default timeout. The same response is returned when a `/search` request exceeds the 30-second default overall deadline, and the active OpenSearch request is aborted.
Expand Down
Loading
Loading