Skip to content

Add corgea advisories check: pre-install package advisory queries for agents#129

Open
juangaitanv wants to merge 2 commits into
mainfrom
feat/advisories
Open

Add corgea advisories check: pre-install package advisory queries for agents#129
juangaitanv wants to merge 2 commits into
mainfrom
feat/advisories

Conversation

@juangaitanv

Copy link
Copy Markdown
Contributor

Summary

Adds a read-only corgea advisories check command so agents (and humans) can query the Corgea vuln-api before deciding to install a package or while threat modeling — instead of only learning a package is bad when the corgea npm|pip|... install-wrap gate blocks it.

All lookups go to the vuln-api at https://cve-worker-staging.corgea.workers.dev (the existing DEFAULT_VULN_API_URL), overridable via CORGEA_VULN_API_URL.

Usage

corgea advisories check npm [email protected]   # version verdict — exit 1, per-advisory "fixed in", safe-version steer
corgea advisories check npm axios          # all advisories for the package (pick a safe version before pinning)
corgea advisories check pypi requests --json   # stable schema_version:1 document for agents

Exit codes: 0 clean / not in advisory DB, 1 advisories found, 2 error.

Design

  • Versioned form reuses the install gate's /check client — identical verdict semantics and guards on both surfaces; no drift between "check said fine" and "install blocked".
  • Unversioned form hits the public /v1/packages/:ecosystem/:name profile route via a new fetch_package_profile (tolerant structs, 404 → "not in advisory database", capped listing flagged as truncated).
  • Auth isolation preserved: shared resolve_vuln_api_access — a custom CORGEA_VULN_API_URL never receives the Corgea token unless CORGEA_VULN_API_SEND_TOKEN_TO_CUSTOM_URL=1. Verified by a live header-capture test during validation.
  • Shared response handling (shared_status_error, verify_response_identity) deduped between /check and the profile route so the confused-deputy guards can't drift.
  • skills/corgea/SKILL.md gains an ### Advisories section instructing agents to check before installing (server-side skill publish is a follow-up; installed agents fetch skill content from the server).

Testing

  • 18 new e2e tests (tests/cli_advisories.rs) against the hermetic vuln-api stub: both forms × text/json × exit codes, stdout purity.
  • Contract tests (tests/vuln_api_contract.rs, --ignored) round-trip live staging responses through the CLI deserializers.
  • Full suite green: 485 tests, ./harness check clean (strict clippy, fmt, skill-drift).
  • Live staging smokes: [email protected] → exit 1 (23 advisories, safe version 0.32.0); unknown package → exit 0; --json emits one valid document.

Implement read-only pre-install advisory lookup against Corgea vuln-api:
- New advisories.rs subcommand with <ecosystem> <package>[@Version] args
- Reuses /check client for versioned package lookups
- New package-profile endpoint query for unversioned threat-modeling
- Human-readable output plus --json mode
- Exit codes: 0 (clean), 1 (advisories found), 2 (error)
- Extends vuln_api client and precheck rendering
- Includes comprehensive test fixtures and CLI integration tests
- Updated SKILL.md with command documentation
Comment thread src/vuln_api/mod.rs
…entinel

A 404 without {"error":"Package not found"} (wrong host, older
deployment without the route, proxy/CDN) now errors with exit 2 instead
of reading as "no known advisories". Stub already distinguished the
two; adds unit, e2e, and staging-contract coverage.
Comment thread src/advisories.rs
return Err("package spec is empty".to_string());
}
let (name, version) = match spec.rfind('@') {
Some(0) | None => (spec, None),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think for pypi we should also accept == as a version separator

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also handle extras like "requests[security]"

Comment thread src/advisories.rs
Some(0) | None => (spec, None),
Some(pos) => (&spec[..pos], Some(&spec[pos + 1..])),
};
if name.is_empty() || name == "@" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we trip the name?

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.

3 participants