← Back to scanner

REST API

conda-cve.tech exposes a small JSON HTTP API. Base URL: (same host as this page unless you run the CLI elsewhere). Machine-readable schema: /openapi.json.

Endpoints

GET /health

Liveness probe for load balancers and orchestrators.

Response 200:

{ "status": "ok" }

GET /openapi.json

OpenAPI 3.0 description of this API.

POST /v1/scan/stream

Same inputs as /v1/scan, but the response is NDJSON (application/x-ndjson): one JSON object per line. The web UI uses this endpoint so results appear package-by-package. Event types: started, progress, package, done, error.

POST /v1/scan

Parse a conda ecosystem lockfile and return a structured vulnerability report.

Provide exactly one lockfile source: file upload, remote http(s) URL, or inline content. Lockfile format is detected from file content, not from the filename or extension.

POST /v1/scan — request options

Content-Type Fields Description
multipart/form-data lockfile Upload the lockfile (browser / curl -F).
multipart/form-data url Remote http(s) URL to fetch.
application/json content Lockfile body as a JSON string.
application/json url Same semantics as multipart url.
application/json filename (optional) Optional name hint; format detection still uses content.
URLs must use http:// or https://. The server fetches the lockfile remotely; private and localhost hosts are blocked (SSRF protection). GitHub github.com/…/blob/… and …/raw/… links are rewritten to raw.githubusercontent.com before fetch.

Examples

Replace $BASE with your API origin (e.g. ).

Upload file

curl -F lockfile=@pixi.lock "$BASE/v1/scan"

Remote URL (JSON)

curl -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/conda-lock.yml"}' \
  "$BASE/v1/scan"

Inline content (JSON)

curl -H 'Content-Type: application/json' \
  -d '{"content":"# lockfile…","filename":"conda-lock.yml"}' \
  "$BASE/v1/scan"

POST /v1/scan — responses

StatusMeaning
200Scan completed; body is a scan report (JSON).
400Invalid or unrecognized lockfile, bad URL, size limit, or conflicting fields. Body: { "error": "…" }.
502Upstream failure (vulnerability lookup, package mapping, or URL fetch). Body: { "error": "…" }.

Lock updates

Lock updates are performed in the web UI using mambajs (browser WASM solver). Supported formats: mamba JSON (lockVersion), conda explicit (@EXPLICIT), conda-lock YAML, and pixi/rattler locks. The UI imports the lock, re-solves selected packages, exports the same format, then rescans via POST /v1/scan.

The final done event on POST /v1/scan/stream may include lock_content (echo of the scanned file) so URL-based scans can be updated in the browser.

Scan report (200)

Top-level fields:

FieldDescription
lockfile_formatDetected format (e.g. conda-lock-yaml, mambajs-json).
scanned_atISO 8601 timestamp (UTC).
statsCounts: package_count, packages_with_cves, packages_checked, packages_not_checked, plus per-lookup-path query totals.
packagesArray of per-package results (see below).
infoOptional informational strings (e.g. served from lockfile snapshot cache).
warningsOptional strings (e.g. rate limits, partial failures).

Each element of packages:

FieldDescription
name, versionConda package identity from the lockfile.
managerconda or pypi.
cve_lookupHow the package was mapped (method, PyPI targets, channel).
coveragechecked (bool) and per-source sources[] status entries.
cvesCVE list with id, severity, summary, references.
Interpreting empty CVE lists: Treat cves: [] as “no known CVEs for this version” only when coverage.checked is true. If coverage.checked is false, the package was not fully scanned — do not assume it is safe.

Limits & environment

← Back to scanner