Branch: feat/osv-package-cve-lookup
Date: 2026-07-09
Status: Open
get_dependency_blast_radius showed blast-radius exposure metrics (downloads,
dependents) for direct package queries but never asked: does this package have
known CVEs? The OSV /v1/query endpoint existed and was used elsewhere in the
codebase (for CVE→affected-packages lookups) but was never called in the direct
package path.
New helper _fetch_osv_package_vulns(name, ecosystem, version, max_vulns):
- POSTs to
https://api.osv.dev/v1/querywith package + optional version _ECOSYSTEM_TO_OSVdict maps 31 input aliases → canonical OSV ecosystem strings (covers PyPI, npm, Maven, Go, crates.io, RubyGems, NuGet, Packagist, Hex, Pub, Conda)- Parses id, summary (≤120 chars), aliases, fixed version from range events
- Graceful empty-list return on all errors
get_dependency_blast_radius direct package path:
- Calls
_fetch_osv_package_vulnspost-enrichment; version-scoped when version given - New output section:
Known CVEs (OSV) affecting @X.Y.Z: Nwith per-advisory bullets - Summary line:
Known CVEs from OSV affecting version X.Y.Z: N - CVE input path unchanged (function never called there)
35 new tests across TestEcosystemToOsvMapping, TestFetchOsvPackageVulns,
TestBlastRadiusOsvIntegration. Suite: 1193 passed (was 1158).
- Swift Package Index enricher —
_enrich_swift: API atswiftpackageindex.com/api/packages/{owner}/{package}; complication is needing owner/repo format; map to OSV ecosystemSwiftURL - Conda enricher —
_enrich_condais already in PR #110; check if merged - Extend
_ECOSYSTEM_TO_OSVto cover Conda/Bioconda once PR #110 lands first_release_datefor crates.io (extend PR #103 analogue)
Added _enrich_cran() enricher to get_dependency_blast_radius.py, extending
the blast-radius tool with native CRAN (R) package support.
- Checked all open PRs (#103–#112): none covered CRAN.
- OSV ecosystem list confirms
CRANas a valid, active ecosystem with real advisories (e.g.,jsonlite,openssl,httrpackages). - Swift Package Index API returned 401 (auth required) — ruled out.
- ConanCenter API returned HTML/404 for REST queries — ruled out.
- crandb and cranlogs: both free, unauthenticated, JSON, confirmed working.
Constants: _CRANDB_URL, _CRANLOGS_URL
New helper: _parse_cran_timestamp(ts) — normalises crandb ISO-8601
timestamps ("2014-10-21T08:27:55+00:00" or "...Z") to "YYYY-MM-DD" by
slicing the first 10 characters.
New enricher: _enrich_cran(name):
- Call 1:
crandb.r-pkg.org/{name}/all→ latest version, title (max 120 chars), archived flag,revdeps(→dependent_packages_count), version timeline count, first-release date, age in years, CRAN page URL. - Call 2:
cranlogs.r-pkg.org/downloads/total/last-month/{name}→ monthly downloads;weekly_downloads = monthly // 4(integer floor division). - Independent try/except per call for graceful degradation.
- Both-fail fallback:
{ecosystem: "CRAN", package_name: name}without raising.
Dispatcher: eco_lower in ("cran", "r") in _enrich_package — covers
cran:openssl and r:openssl input forms.
Output block: title, latest version, total versions, reverse deps, monthly
downloads, first release + age, archived status, CRAN page URL. Fixed npm
dependents label to show only for npm ecosystem (previously shown for any
ecosystem with dependent_packages_count).
30 new tests (6 classes, all HTTP mocked):
TestParseCranTimestamp (6), TestEnrichCranHappyPath (16),
TestEnrichCranDegradation (7), TestEnrichPackageCranDispatch (5),
TestBlastScoreWithCranData (6), TestGetDependencyBlastRadiusCran (9).
Suite: 1206 passed (was 1158 before this session series; +30 this PR). 3 deselected, 3 warnings — all pre-existing, zero regressions.
- Hackage enricher (
_enrich_hackage) — Haskell package registry; OSV ecosystemHackage; API:hackage.haskell.org/package/{name}.json(free, unauthenticated). Revdeps viahackage.haskell.org/package/{name}/reverse. - opam enricher (
_enrich_opam) — OCaml package registry; OSV ecosystemOSS-Fuzz/crates.ioalignment; API:opam.ocaml.org/pkg/{name}/latest(JSON, no auth). - OSV
_ECOSYSTEM_TO_OSVcoverage — extend the mapping to include CRAN once this PR merges. - Per-version CVE integration for CRAN —
manus-agent blast-radius cran:openssl@2.1.1should call_fetch_osv_package_vulns("openssl", "CRAN", "2.1.1").
Added tests/conftest.py with shared pytest fixtures and tests/test_conftest_fixtures.py
(50 tests) that validates and documents them.
30+ test files independently define their own mock factories (tool_use dicts, HTTP responses, NVD/EPSS/KEV payloads). This leads to duplicated helpers, inconsistent mock shapes, and higher friction when writing new tests. A shared conftest.py is the standard pytest solution.
make_tool_use— builds Strands tool_use dicts with auto-generated IDsmock_http_response— creates mock requests.Response with raise_for_status()nvd_cve_factory/nvd_api_response— builds NVD CVE payloadsepss_data_factory— builds EPSS API responseskev_catalog_factory— builds CISA KEV catalog payloadsosv_record_factory— builds OSV.dev records- Config fixtures (default, bedrock, openai, anthropic, ollama)
tmp_history_file/tmp_config_file— temp filesystem helpersenv_override— clean monkeypatch wrapper- Module constants:
SAMPLE_CVE_LOG4SHELL,SAMPLE_CVE_XZ
- 50 new fixture validation tests pass
- All 1208 existing tests unchanged / passing
- Ruff clean
_run_changelog_generatetest coverage — the changelog CLI tests (test_changelog_cli.py) are comprehensive but_run_changelog_generatecould use edge-case tests for merge commits, non-conventional commits mixed in, and empty repos.- BrowserUseAgent.stream_async tests —
stream_async()uses asyncio.Queue with step/done callbacks; no tests cover the streaming yield/queue pattern. - WorkflowAgent / Orchestrator tests —
Orchestrator.run()currently just delegates to WorkflowAgent; tests for theTaskPlan,OrchestratorResult, andAgentTypedata structures + error handling. - Refactor existing tests to use conftest fixtures — once PR #158 merges, existing test files can be simplified by replacing local helpers with shared fixtures.
PR: #159
Branch: feat/test-stream-async-browser-agent
File: tests/test_browser_use_stream_async.py (+1548 lines)
stream_async() is a 165-line async generator with callbacks, queue management,
error handling, and cleanup logic. Existing tests only covered the fallback path
(2 tests when BrowserUse is None), leaving zero coverage of the real streaming
path: step_callback, done_callback, queue draining, background task, keep_alive
timeout, and finally-block cleanup.
45 tests in 7 classes:
- Fallback path (5): BrowserUse/BrowserProfile/Controller unavailable
- True streaming path (11): callbacks, queue flow, extracted content, output_model
- Error handling (7): constructor/LLM/callback failures, post-done exceptions
- Browser cleanup (7): close(), keep_alive timeout, error resilience
- Input handling (4): string/list/empty task parsing
- Task cancellation (2): background task lifecycle
- Configuration (4): headless, output_model, enable_memory, patch config
- Edge cases (8): missing attributes, mixed types, validate_output
- 45 new tests pass
- All 1203 tests pass (up from 1158), no regressions
- Ruff clean
- WorkflowAgent / Orchestrator tests —
Orchestrator.run()delegates to WorkflowAgent; tests forTaskPlan,OrchestratorResult,AgentTypedata structures + error handling. _run_browser_tasktests — the non-streaming browser task method has complex try/finally with keep_alive/timeout logic worth covering.- CLI
vendor-response/verify-exploitsubcommand tests — several open PRs add new subcommands but many lack unit tests for argument parsing. - Refactor existing tests to use conftest fixtures — once PR #158 merges, existing test files can be simplified.
Branch: test/check-cisa-kev-suite
PR: manus-use#165
Tests added: 43
- TOOL_SPEC schema validation (5 tests)
_get_kev_datacaching logic: fresh/stale/missing cache, network errors, cache write, malformed cache, missing timestamp (8 tests)check_cisa_kevmain function: CVE found/not-found, case-insensitive, exact match, multiple CVEs, empty catalog, missing key, invalid inputs, tool_use_id propagation (15 tests)log_tool_output_sizeintegration — every exit path (4 tests)- Edge cases: single-entry catalog, mixed-case, missing key, content structure (8 tests)
- Module constants validation (3 tests)
_get_kev_data() does not handle corrupted cache files gracefully —
json.loads() on a malformed .cisa_kev_cache.json propagates
JSONDecodeError instead of falling through to a fresh API fetch.
Documented in test.
- 43 new tests pass
- Full suite: 1201 passed, 0 failures, 0 regressions
- Ruff clean (lint + format)
get_cwe_detailstool tests — another core tool with zero test coverage; similar structure (HTTP fetch + HTML parsing + error paths)obtain_cvestool tests — complex multi-source aggregation pipeline (NVD + GitHub + EPSS + KEV + webhook) with zero unit testssearch_poc_sourcestool tests — parallel 5-source aggregator with dedup/sort logic; existingtest_search_poc_sources.pyonly covers basic cases- Cache robustness fix PR — wrap
json.loads()in_get_kev_datawith try/except to gracefully handle corrupted cache
What: New decode_cvss_vector tool + decode-cvss CLI subcommand that parses CVSS v3.0/v3.1 vector strings and produces structured breakdowns with:
- Per-metric human-readable explanations
- Computed base score (exact CVSS v3.1 formula)
- Severity classification
- Natural-language attack summary
- Remediation priority with escalation factors
Why: The project collects CVSS vectors from multiple sources (NVD, VulnCheck, patch-diff) but never explains what they mean. This fills the gap between raw scores and actionable security context.
Tests: +70 new tests (1228 total passing, up from 1158 baseline) Branch: feat/cvss-vector-decoder PR: manus-use#112
Branch: feat/cve-enrich
What: Lightweight multi-source CVE enrichment tool that fetches NVD, EPSS, CISA KEV, OSV.dev, and VulnCheck data in parallel. Returns unified risk snapshot with composite scoring. No LLM agent required.
CLI: manus-agent enrich CVE-XXXX-YYYY [--output json|text] [--no-vulncheck]
Tests: +43 new tests (all fetchers, risk computation, CLI modes, Strands interface)
Suggested next: test suite for _run_discover CLI execution (VulnerabilityDiscoveryAgent mocking), or Config.from_file() edge cases, or obtain_cves.py unit tests