Determinism Benchmark (cross-scanner) — Stable (2025-11)

Source: advisory “23-Nov-2025 - Benchmarking Determinism in Vulnerability Scoring”. This doc captures the runnable harness pattern and expected outputs for task BENCH-DETERMINISM-401-057.

Goal

Minimal harness (Python excerpt)

# run_bench.py (excerpt) — deterministic JSON hashing
def canon(obj):
    return json.dumps(obj, sort_keys=True, separators=(',', ':')).encode()

def shas(b):
    return hashlib.sha256(b).hexdigest()

for sbom, vex in zip(SBOMS, VEXES):
    for scanner, tmpl in SCANNERS.items():
        for mode in ("canonical", "shuffled"):
            for i in range(10):
                if mode == "shuffled":
                    sb, vx = shuffle(sbom), shuffle(vex)
                out = run(tmpl.format(sbom=sb, vex=vx))
                norm = normalize(out)  # purl, vuln id, base_cvss, effective
                blob = canon({"scanner": scanner, "sbom": sbom,
                              "vex": vex, "findings": norm})
                results.append({
                    "hash": shas(blob), "mode": mode,
                    "run": i, "scanner": scanner, "sbom": sbom
                })

Inputs

Metrics

Deliverables


How to run (local)

cd src/Tools/StellaOps.Bench/Determinism

# Run determinism bench (uses built-in mock scanner by default; defaults to 10 runs)
python run_bench.py --sboms inputs/sboms/*.json --vex inputs/vex/*.json \
  --config configs/scanners.json --shuffle --output results

# Reachability dataset (optional)
python run_reachability.py --graphs inputs/graphs/*.json \
  --runtime inputs/runtime/*.ndjson --output results

Outputs are written to results.csv (determinism), results-reach.csv/results-reach.json (reachability hashes), and manifests inputs.sha256 + dataset.sha256 (if reachability). Feed bundle hashes live in the same manifest when provided via DET_EXTRA_INPUTS.

How to run (CI)

Offline/air-gap workflow

  1. Place feeds bundle (see src/Tools/StellaOps.Bench/Determinism/inputs/feeds/README.md), SBOMs, VEX, and optional reachability corpus under offline/inputs/ with matching inputs.sha256 and (if reachability) dataset.sha256. A sample inputs/inputs.sha256 is provided for the bundled demo SBOM/VEX/config.
  2. Run ./offline_run.sh --inputs offline/inputs --output offline/results (script lives under src/Tools/StellaOps.Bench/Determinism) to execute benches without network (defaults: runs=10, threshold=0.95; manifest verification on). Use --no-verify to skip hash checks if manifests are absent.
  3. Store outputs plus manifests in Offline Kit; include DSSE envelope if signing is enabled (./sign_results.sh).

Notes