Repository navigation
v0.1.0 — first feature-complete release
First feature-complete release.
Pipeline
- extract — ELF parser written in C (
elfdump.c, loaded with ctypes) with a pyelftools
fallback that must produce identical results; PE via pefile (imports, VS_VERSION_INFO).
Version-string candidates keep their file offsets. Corrupted inputs are bounds-checked and
fuzzed in tests. - identify — 10 CPE-grounded YAML signature rules (OpenSSL, zlib, curl, SQLite, Expat,
libpng, BusyBox, PCRE2, libxml2, nginx); components are marked bundled (code inside the
file, matched) or linked (a dependency to scan separately). - identify
--llm-hint(opt-in) — version strings no rule claimed go to the LLM; a
suggestion is kept only if the version occurs verbatim at the cited offset and its CPE
vendor:product is on an allowlist (every extra entry checked against the NVD CPE API on
2026-10-23). Accepted/rejected counts are traced. - match — NVD CPE query with a local range re-check,
fixed_infrom the range ends, OSV
references as enrichment; disk cache and recorded fixtures for offline runs. - retrieve — allowlisted advisory fetcher (redirects re-checked, size cap, per-host
spacing), SQLite FTS5/BM25 index with a pure-Python BM25 fallback. Debian/Ubuntu tracker
pages and recorded fixture pages are looked up for every CVE, not only NVD references;
one passage per page is taken before a second from the same page. - advise — Anthropic (structured output) or Ollama (JSON schema) writes the Korean guide
from a facts JSON plus<document>-wrapped passages; injection-looking passages are flagged.
Batch size is provider-aware (Ollama 4 CVEs per call, Anthropic 12;--batch-size
overrides) after CPU Ollama timed out on 12-CVE batches; the Ollama request timeout is
BCPG_OLLAMA_TIMEOUT(default 600 s). Null-likefixed_instrings from the model
("null","None","N/A","없음","", …) are coerced to null and whitespace is
stripped before the gate; the count is traced asnormalized_fields. - validate — deterministic gate, rules (a)–(g) on the structured fields and (h)–(j) on the
free text: inline citations must belong to the CVE (and to the finding's evidence), every
version in the text must be installed / afixed_in/ a range bound, no upgrade target for a
CVE without a fixed version, and priority words next to a CVE id must match its CVSS
priority. Rejections are sent back verbatim (≤ 2 retries), then the template is used. - report — Korean
report.md,report.json, andtrace.jsonwith every stage, attempt,
rejection reason, token count and page-fetch outcome.
Tools
bcpg scan,bcpg identify,bcpg bench [--sets] [--online].bcpg-mcpMCP server:scan_binary,lookup_cve,identify_strings.- Benchmark: synthetic (10 binaries) and distro (44 real libraries from Debian 10/11 and
Ubuntu 18.04/20.04) — bundled-component precision/recall and version accuracy 100%.
Quality
- Test suite runs with zero network and zero LLM calls (recorded NVD/OSV/page fixtures,
scripted fake provider);tests/conftest.pyblocks non-loopback sockets and the Ollama
port, stubs the Ollama probe and clears provider/API-key/offline variables, so local
services and shell settings cannot change results. The Anthropic SDK is imported only when
a real client is built or an SDK error is mapped, which took a cold-venv run from 46 s to
13 s on Windows (about 10 s warm). CI on Ubuntu with the optional extras installed. - Sample reports in
docs/sample/: zlib 1.2.11 regenerated live with 0.1.0 (CPU Ollama; the
gate rejected all three replies, so the template report shipped) and a template OpenSSL
1.1.1n report.