BinaryIndex

Status: Implemented Source: src/BinaryIndex/ Owner: BinaryIndex Guild (Scanner-integrated)

Purpose

BinaryIndex detects vulnerable binaries independently of package metadata. Package version strings can lie — backports, custom builds, and stripped metadata all defeat name/version matching — so BinaryIndex identifies vulnerabilities binary-first, using Build-IDs, hash catalogs, function fingerprints, and delta (patch) signatures. It adds backport-aware fix resolution and emits signed (DSSE) evidence plus VEX candidates describing patch status.

Audience: Scanner integrators and operators who need defensible vulnerable-binary detection where package metadata is untrustworthy, and curators maintaining the golden-set and ground-truth corpora.

Services

BinaryIndex ships as three deployable services plus a large library set (router service names binaryindex and symbols; default port 8080).

API Surface

BinaryIndex WebService (binaryindex)

Vulnerability resolution (Controllers/ResolutionController.cs, route api/v1/resolve):

MethodRoutePurpose
POST/api/v1/resolve/vulnResolve vulnerability status for a single binary (optional ?bypassCache=true).
POST/api/v1/resolve/vuln/batchBatch resolution (max 500 items per Resolution:MaxBatchSize).

Golden-set curation (Controllers/GoldenSetController.cs, route api/v1/golden-sets):

MethodRoutePurpose
GET/api/v1/golden-setsList golden sets (component, status, tags, limit 1–500, offset, orderBy).
GET/api/v1/golden-sets/{id}Get a golden set by ID (CVE/GHSA).
POST/api/v1/golden-setsCreate a golden set (starts in Draft).
PATCH/api/v1/golden-sets/{id}/statusWorkflow transition (Draft → InReview → Approved → Deprecated/Archived).
GET/api/v1/golden-sets/{id}/auditAudit log for a golden set.
DELETE/api/v1/golden-sets/{id}Soft-delete (archive) a golden set.

Patch coverage / Patch Map Explorer (Controllers/PatchCoverageController.cs, route api/v1/stats/patch-coverage):

MethodRoutePurpose
GET/api/v1/stats/patch-coverageAggregated vulnerable/patched/unknown counts per CVE for heatmaps.
GET/api/v1/stats/patch-coverage/{cveId}/detailsFunction-level coverage breakdown for a CVE.
GET/api/v1/stats/patch-coverage/{cveId}/matchesPaginated matching images for a CVE (state = vulnerable/patched/unknown).

Ops / observability (Controllers/BinaryIndexOpsController.cs, route api/v1/ops/binaryindex):

MethodRoutePurpose
GET/api/v1/ops/binaryindex/healthLifter warmness + cache availability.
POST/api/v1/ops/binaryindex/bench/runQuick latency benchmark (1–1000 iterations).
GET/api/v1/ops/binaryindex/cacheFunction IR cache statistics.
GET/api/v1/ops/binaryindex/configEffective configuration (secrets redacted).

Health/liveness/readiness (/health, /healthz, /readyz) and BuildInfo are mapped anonymously for container probes.

Symbols Server (symbols)

Symbol manifests (Program.cs): POST /v1/symbols/manifests, GET /v1/symbols/manifests/{manifestId}, GET /v1/symbols/manifests, POST /v1/symbols/resolve, GET /v1/symbols/by-debug-id/{debugId}. Symbol sources & marketplace (Endpoints/SymbolSourceEndpoints.cs): GET/POST/PUT/DELETE /api/v1/symbols/sources*, GET /api/v1/symbols/marketplace*, POST /api/v1/symbols/marketplace/{entryId}/install|uninstall, POST /api/v1/symbols/marketplace/sync.

Key DTOs (StellaOps.BinaryIndex.Contracts/Resolution/VulnResolutionContracts.cs)

Components

The module comprises ~40 libraries under src/BinaryIndex/__Libraries/ plus the three services above. Highlights:

Identity & resolution:

Delta-signature (backport detection) stack:

Semantic-diffing stack (implemented):

Corpus & ground truth:

Symbols stack: StellaOps.Symbols.Core, .Infrastructure, .Client, .Bundle, .Marketplace.

Configuration

Each service binds its own configuration; BinaryIndex is not embedded in Scanner/Concelier settings.

BinaryIndex WebService (appsettings.json):

Core library options (StellaOps:BinaryIndex section, BinaryIndexOptions): B2R2Pool (per-ISA lifter pool, warm-preload ISAs intel-64/intel-32/armv8-64/armv7-32), SemanticLifting (B2R2Version 0.9.1, NormalizationRecipeVersion v1), FunctionCache, Persistence (schema, pooling, retries), and Ops (endpoint toggles, redacted keys).

Key capabilities:

Pluginized Runtime Composition

BinaryIndex uses the shared plugin probe surface for analyzer/data-pack classification:

Compose plugin overlays mount the canonical roots for binaryindex-web:

PurposeHost pathContainer path
Executable analyzer bundlesdevops/plugins/binaryindex/recommended/, devops/plugins/binaryindex/harness//app/plugins/binaryindex/recommended, /app/plugins/binaryindex/harness
Operator config/data-pack registrydevops/etc/plugins/binaryindex//app/etc/plugins/binaryindex
Analyzer trust rootsdevops/etc/certificates/trust-roots/plugins/binaryindex//app/trust-roots/plugins/binaryindex
Probe scratchnamed volume/var/lib/stellaops/plugin-scratch/binaryindex

Base compose also mounts Router/Messaging bundle roots read-only into binaryindex-web for shared Router registration transport. Those mounts use /app/plugins/router/base, /app/plugins/messaging/base, and /app/trust-roots/plugins/router; they are not BinaryIndex analyzer bundles.

devops/etc/plugins/binaryindex/registry.yaml mirrors the current analyzer surface catalog. Core host entries (binaryindex.identity.build-id, binaryindex.parser.*, and binaryindex.fingerprint.stable-hash) must work in the base image and are not represented by a mounted base bundle. The packaging script can produce signed executable analyzer bundles for binaryindex.disassembly.iced and binaryindex.disassembly.b2r2:

.\devops\build\package-runtime-plugins.ps1 -Module binaryindex -Profile recommended -SignBinaryIndexBundles -UseOfflineDevSigner
.\devops\build\package-runtime-plugins.ps1 -Module binaryindex -Profile harness -SignBinaryIndexBundles -UseOfflineDevSigner

binaryindex.disassembly.ghidra and binaryindex.corpus.builder remain future executable analyzer/corpus-builder producers. All optional executable analyzers are non-required and report notMounted until runtime loader admission validates the mounted manifest, checksums, payload, and signature before code load. binaryindex.datapack.* entries remain non-executable data packs, report disabled, and must not be loaded as plugins.

The WebService no longer compiles the optional B2R2 analyzer implementation or Router/Messaging transport implementation payload directly. Its ops controller reports the lifter as not-mounted until a signed analyzer bundle is admitted. The base mounted-runtime proof on 2026-06-07 rebuilt stellaops/binaryindex-web:dev in mounted-plugin mode, passed image audit, started healthy, and returned POST /internal/plugins/probe with isComplete=true for the five required host-core rows. The Worker still references StellaOps.BinaryIndex.Builders for the current reproducible-build job, so corpus-builder externalization remains future loader work.

StellaOps.Symbols.Server is de-scoped from BinaryIndex analyzer bundle mounts until it exposes its own executable plugin/probe contract. Symbols continues to serve the symbols:* API surface without /internal/plugins/* endpoints.

CLI

Delta-signature commands ship in the CLI (src/Cli/StellaOps.Cli/Commands/DeltaSig/, plugin StellaOps.Cli.Plugins.DeltaSig):

stella deltasig extract    # Extract signatures from a binary
stella deltasig author     # Author a vuln/patched signature pair
stella deltasig sign       # Sign a signature as a DSSE envelope
stella deltasig verify     # Verify a signed signature
stella deltasig match      # Match a binary against signatures
stella deltasig pack       # Create a signature pack (ZIP)
stella deltasig inspect    # Inspect a signature or envelope

Ground-truth validation commands ship under StellaOps.Cli.Plugins.GroundTruth.

Persistence

PostgreSQL schema binaries (with binaries_app helper schema and forced row-level security per tenant_id). One live embedded migration — StellaOps.BinaryIndex.Persistence/Migrations/001_v1_binaryindex_baseline.sql — carries the collapsed pre-1.0 chain (the old 001_initial_schema.sql005_validation_kpis.sql files are archived under Migrations/_archived/pre_1.0/mig061/ and are not embedded); the Symbols server has its own baseline under StellaOps.Symbols.Server/Migrations/001_v1_symbols_server_baseline.sql. Core tables (baseline) include:

Valkey/Redis holds the authoritative resolution cache. The WebService no longer falls back to in-memory stores for golden sets, vulnerability data, delta signatures, or the resolution cache.

Dependencies

Current Status

Library and service implementation is complete: ELF (Build-ID), PE (CodeView GUID), and Mach-O (UUID) identity extraction; multi-architecture disassembly (Iced + B2R2); deterministic normalization; delta-signature generation/matching; backport-aware fix index; golden-set curation; and a VEX bridge. The semantic-diffing stack (IR semantics, decompiler/AST comparison, Ghidra integration, ML similarity, ensemble fusion) is implemented as shipped libraries — see the note below. BinaryIndex is integrated into Scanner’s native binary analysis pipeline.


Appendix — Semantic Diffing (shipped; original phasing retained for context)

Reconciliation note. Earlier revisions of this document described semantic-level binary diffing as a future roadmap. The work has since shipped: the four SPRINT_20260105_001_*_BINDEX_semdiff_* sprints are archived under docs-archive/implplan/, and the corresponding libraries (StellaOps.BinaryIndex.Semantic, .Decompiler, .Ghidra, .ML, .Ensemble) exist in src/BinaryIndex/__Libraries/. The phase tables and metrics below are retained for historical context and reflect the original design phasing and targets, not re-validated current status.

Semantic-level binary diffing detects function equivalence based on behavior rather than syntax, addressing limitations in byte/symbol-based matching when dealing with:

Phases (delivered)

PhaseDescriptionImpactStatus
Phase 1IR-Level Semantic Analysis+15% accuracy on optimized binariesDelivered (StellaOps.BinaryIndex.Semantic)
Phase 2Function Behavior Corpus+10% coverage on stripped binariesDelivered (StellaOps.BinaryIndex.Corpus)
Phase 3Ghidra Integration+5% edge case handlingDelivered (StellaOps.BinaryIndex.Ghidra)
Phase 4Decompiler and ML Similarity+10% obfuscation resilienceDelivered (StellaOps.BinaryIndex.Decompiler, .ML, .Ensemble)

Libraries (shipped)

Target Outcomes (original goals)

MetricBaselineTarget
Patch detection accuracy~70%92%+
Function identification (stripped)~50%85%+
False positive rate~5%<2%

The accuracy/coverage percentages above are the original design targets; they are not re-validated KPIs. Live validation KPIs are tracked via StellaOps.BinaryIndex.Validation and the groundtruth.validation_kpis / validation_pair_kpis / kpi_baselines / regression_checks tables in the persistence baseline 001_v1_binaryindex_baseline.sql.

Sprint Files (archived)

Architecture Documentation

See ./semantic-diffing.md for comprehensive architecture documentation.