Add signal contracts for reachability, exploitability, trust, and unknown symbols
- Introduced `ReachabilityState`, `RuntimeHit`, `ExploitabilitySignal`, `ReachabilitySignal`, `SignalEnvelope`, `SignalType`, `TrustSignal`, and `UnknownSymbolSignal` records to define various signal types and their properties. - Implemented JSON serialization attributes for proper data interchange. - Created project files for the new signal contracts library and corresponding test projects. - Added deterministic test fixtures for micro-interaction testing. - Included cryptographic keys for secure operations with cosign.
This commit is contained in:
207
docs/modules/scanner/design/binary-evidence-alignment.md
Normal file
207
docs/modules/scanner/design/binary-evidence-alignment.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Binary Evidence Alignment with SBOM/VEX Outputs (SC6)
|
||||
|
||||
Status: Draft · Date: 2025-12-04
|
||||
Scope: Define how binary-level evidence (build-id, symbols, patch oracle) aligns with SBOM/VEX outputs to feed policy engines and VEX decisioning.
|
||||
|
||||
## Objectives
|
||||
|
||||
- Link binary-level evidence to SBOM component identities.
|
||||
- Ensure evidence fields are available for policy/VEX correlation.
|
||||
- Define required joins between binary analysis and vulnerability data.
|
||||
- Enable deterministic evidence chain from binary → SBOM → VEX → policy.
|
||||
|
||||
## Evidence Types
|
||||
|
||||
### Build Identity Evidence
|
||||
|
||||
| Evidence Type | Source | SBOM Field | VEX Field | Policy Input |
|
||||
|---------------|--------|------------|-----------|--------------|
|
||||
| Build ID | ELF `.note.gnu.build-id` | `component.properties[evidence:build-id]` | `statement.products[].identifiers.buildId` | `binary.buildId` |
|
||||
| Go Build Info | `runtime.BuildInfo` | `component.properties[evidence:go-build]` | n/a | `binary.goBuildInfo` |
|
||||
| PE Version | PE resource section | `component.properties[evidence:pe-version]` | n/a | `binary.peVersion` |
|
||||
| Mach-O UUID | LC_UUID command | `component.properties[evidence:macho-uuid]` | n/a | `binary.machoUuid` |
|
||||
|
||||
### Symbol Evidence
|
||||
|
||||
| Evidence Type | Source | SBOM Field | VEX Field | Policy Input |
|
||||
|---------------|--------|------------|-----------|--------------|
|
||||
| Exported Symbols | ELF `.dynsym` / PE exports | `component.properties[evidence:symbols-hash]` | n/a | `binary.symbolsHash` |
|
||||
| Debug Symbols | DWARF / PDB | `component.properties[evidence:debug-hash]` | n/a | `binary.debugHash` |
|
||||
| Function Names | Symbol table | `component.properties[evidence:functions]` | `statement.justification.functions` | `binary.functions[]` |
|
||||
|
||||
### Patch Oracle Evidence
|
||||
|
||||
| Evidence Type | Source | SBOM Field | VEX Field | Policy Input |
|
||||
|---------------|--------|------------|-----------|--------------|
|
||||
| Patch Signature | Function hash diff | `component.properties[evidence:patch-sig]` | `statement.justification.patchSignature` | `patch.signature` |
|
||||
| CVE Fix Commit | Commit mapping | `component.properties[evidence:fix-commit]` | `statement.justification.fixCommit` | `patch.fixCommit` |
|
||||
| Binary Diff | objdiff hash | `component.properties[evidence:binary-diff]` | n/a | `patch.binaryDiffHash` |
|
||||
|
||||
## Evidence Chain
|
||||
|
||||
```
|
||||
Binary → SBOM Component → VEX Statement → Policy Evaluation
|
||||
│ │ │ │
|
||||
│ │ │ └── policy://input/component/{purl}
|
||||
│ │ └── vex://statement/{cve}/{product}
|
||||
│ └── sbom://component/{purl}
|
||||
└── binary://evidence/{hash}
|
||||
```
|
||||
|
||||
### Join Keys
|
||||
|
||||
| Source | Target | Join Field | Required |
|
||||
|--------|--------|------------|----------|
|
||||
| Binary | SBOM Component | `evidence:hash` → `component.hashes[]` | Yes |
|
||||
| SBOM Component | VEX Product | `component.purl` → `statement.products[].purl` | Yes |
|
||||
| VEX Statement | Policy Input | `statement.cve` → `policy.advisoryId` | Yes |
|
||||
| Binary Evidence | VEX Justification | `evidence:patch-sig` → `justification.patchSignature` | No |
|
||||
|
||||
## Required SBOM Evidence Properties
|
||||
|
||||
For binary evidence to flow through the pipeline, components MUST include:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "library",
|
||||
"name": "openssl",
|
||||
"version": "3.0.0",
|
||||
"purl": "pkg:generic/openssl@3.0.0",
|
||||
"hashes": [
|
||||
{"alg": "SHA-256", "content": "..."}
|
||||
],
|
||||
"properties": [
|
||||
{"name": "evidence:hash", "value": "b3:..."},
|
||||
{"name": "evidence:source", "value": "scanner:binary-analyzer:v1.0.0"},
|
||||
{"name": "evidence:build-id", "value": "abc123..."},
|
||||
{"name": "evidence:symbols-hash", "value": "b3:..."},
|
||||
{"name": "evidence:patch-sig", "value": "b3:..."},
|
||||
{"name": "evidence:confidence", "value": "0.95"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## VEX Integration
|
||||
|
||||
VEX statements can reference binary evidence for justification:
|
||||
|
||||
```json
|
||||
{
|
||||
"vulnerability": "CVE-2025-0001",
|
||||
"products": [
|
||||
{
|
||||
"purl": "pkg:generic/openssl@3.0.0",
|
||||
"identifiers": {
|
||||
"buildId": "abc123...",
|
||||
"evidenceHash": "b3:..."
|
||||
}
|
||||
}
|
||||
],
|
||||
"status": "not_affected",
|
||||
"justification": {
|
||||
"category": "vulnerable_code_not_present",
|
||||
"patchSignature": "b3:...",
|
||||
"fixCommit": "deadbeef...",
|
||||
"functions": ["EVP_EncryptUpdate", "EVP_DecryptUpdate"],
|
||||
"evidenceRef": "cas://evidence/openssl/3.0.0/binary-analysis.json"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Policy Engine Integration
|
||||
|
||||
Policy rules can reference binary evidence fields:
|
||||
|
||||
```rego
|
||||
# policy/scanner/binary-evidence.rego
|
||||
package scanner.binary
|
||||
|
||||
import rego.v1
|
||||
|
||||
# Require build-id for high-severity vulns
|
||||
deny contains msg if {
|
||||
input.vulnerability.severity == "critical"
|
||||
not input.component.properties["evidence:build-id"]
|
||||
msg := sprintf("Critical vuln %s requires build-id evidence", [input.vulnerability.id])
|
||||
}
|
||||
|
||||
# Accept patch oracle evidence as mitigation
|
||||
allow contains decision if {
|
||||
input.component.properties["evidence:patch-sig"]
|
||||
input.vex.status == "not_affected"
|
||||
input.vex.justification.patchSignature == input.component.properties["evidence:patch-sig"]
|
||||
decision := {
|
||||
"action": "accept",
|
||||
"reason": "Patch signature verified",
|
||||
"confidence": input.component.properties["evidence:confidence"]
|
||||
}
|
||||
}
|
||||
|
||||
# Confidence threshold for binary analysis
|
||||
warn contains msg if {
|
||||
conf := to_number(input.component.properties["evidence:confidence"])
|
||||
conf < 0.8
|
||||
msg := sprintf("Low confidence (%v) binary evidence for %s", [conf, input.component.purl])
|
||||
}
|
||||
```
|
||||
|
||||
## Evidence Fields by Binary Format
|
||||
|
||||
### ELF (Linux)
|
||||
|
||||
| Section | Evidence Extracted | Deterministic |
|
||||
|---------|-------------------|---------------|
|
||||
| `.note.gnu.build-id` | Build ID (SHA1/UUID) | Yes |
|
||||
| `.gnu.hash` | Symbol hash table | Yes |
|
||||
| `.dynsym` | Dynamic symbols | Yes |
|
||||
| `.debug_info` | DWARF debug symbols | Yes |
|
||||
| `.rodata` | String literals | Yes |
|
||||
|
||||
### PE (Windows)
|
||||
|
||||
| Section | Evidence Extracted | Deterministic |
|
||||
|---------|-------------------|---------------|
|
||||
| PE Header | Timestamp, Machine type | Partial* |
|
||||
| Resource | Version info, Product name | Yes |
|
||||
| Export Table | Exported functions | Yes |
|
||||
| Import Table | Dependencies | Yes |
|
||||
| Debug Directory | PDB path, GUID | Yes |
|
||||
|
||||
*PE timestamp may be zeroed for reproducible builds
|
||||
|
||||
### Mach-O (macOS)
|
||||
|
||||
| Command | Evidence Extracted | Deterministic |
|
||||
|---------|-------------------|---------------|
|
||||
| LC_UUID | Binary UUID | Yes |
|
||||
| LC_VERSION_MIN | Min OS version | Yes |
|
||||
| LC_BUILD_VERSION | Build version | Yes |
|
||||
| LC_CODE_SIGNATURE | Code signature | Yes |
|
||||
| SYMTAB | Symbol table | Yes |
|
||||
|
||||
## Determinism Requirements
|
||||
|
||||
1. **Stable ordering**: Evidence properties sorted by name
|
||||
2. **Hash computation**: BLAKE3-256 over canonical JSON
|
||||
3. **Confidence scores**: 4 decimal places, `MidpointRounding.ToZero`
|
||||
4. **Function lists**: Sorted lexicographically, deduplicated
|
||||
5. **Symbol hashes**: Computed over sorted symbol names
|
||||
|
||||
## CAS Storage
|
||||
|
||||
Binary evidence artifacts stored in CAS:
|
||||
|
||||
```
|
||||
cas://evidence/{component}/{version}/
|
||||
├── binary-analysis.json # Full analysis result
|
||||
├── symbols.txt # Extracted symbols (sorted)
|
||||
├── functions.txt # Extracted functions (sorted)
|
||||
└── patch-signatures.json # Patch oracle signatures
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- Sprint: `docs/implplan/SPRINT_0186_0001_0001_record_deterministic_execution.md` (SC6)
|
||||
- Roadmap: `docs/modules/scanner/design/standards-convergence-roadmap.md` (SC1)
|
||||
- Contract: `docs/modules/scanner/design/cdx17-cbom-contract.md` (SC2)
|
||||
- Entropy: `docs/modules/scanner/entropy.md`
|
||||
Reference in New Issue
Block a user