345 lines
10 KiB
JSON
345 lines
10 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://stellaops.io/schemas/binarydiff-v1.schema.json",
|
|
"title": "BinaryDiffV1",
|
|
"description": "In-toto predicate schema for binary-level diff attestations between container images",
|
|
"type": "object",
|
|
"required": ["predicateType", "inputs", "findings", "metadata"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"predicateType": {
|
|
"const": "stellaops.binarydiff.v1",
|
|
"description": "Predicate type identifier"
|
|
},
|
|
"inputs": {
|
|
"$ref": "#/$defs/BinaryDiffInputs",
|
|
"description": "Base and target image references"
|
|
},
|
|
"findings": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/BinaryDiffFinding"
|
|
},
|
|
"description": "Per-binary diff findings"
|
|
},
|
|
"metadata": {
|
|
"$ref": "#/$defs/BinaryDiffMetadata",
|
|
"description": "Analysis metadata"
|
|
}
|
|
},
|
|
"$defs": {
|
|
"BinaryDiffInputs": {
|
|
"type": "object",
|
|
"required": ["base", "target"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"base": {
|
|
"$ref": "#/$defs/ImageReference",
|
|
"description": "Base image reference"
|
|
},
|
|
"target": {
|
|
"$ref": "#/$defs/ImageReference",
|
|
"description": "Target image reference"
|
|
}
|
|
}
|
|
},
|
|
"ImageReference": {
|
|
"type": "object",
|
|
"required": ["digest"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"reference": {
|
|
"type": "string",
|
|
"description": "Full image reference (e.g., docker://repo/image:tag)",
|
|
"examples": ["docker://registry.example.com/app:1.0.0"]
|
|
},
|
|
"digest": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
"description": "Image digest in sha256:hex format"
|
|
},
|
|
"manifestDigest": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
"description": "Platform-specific manifest digest"
|
|
},
|
|
"platform": {
|
|
"$ref": "#/$defs/Platform"
|
|
}
|
|
}
|
|
},
|
|
"Platform": {
|
|
"type": "object",
|
|
"required": ["os", "architecture"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"os": {
|
|
"type": "string",
|
|
"description": "Operating system (e.g., linux, windows)",
|
|
"examples": ["linux", "windows"]
|
|
},
|
|
"architecture": {
|
|
"type": "string",
|
|
"description": "CPU architecture (e.g., amd64, arm64)",
|
|
"examples": ["amd64", "arm64", "386"]
|
|
},
|
|
"variant": {
|
|
"type": "string",
|
|
"description": "Architecture variant (e.g., v8 for arm64)",
|
|
"examples": ["v7", "v8"]
|
|
}
|
|
}
|
|
},
|
|
"BinaryDiffFinding": {
|
|
"type": "object",
|
|
"required": ["path", "changeType", "binaryFormat"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "File path within the container filesystem",
|
|
"examples": ["/usr/lib/libssl.so.3", "/usr/bin/openssl"]
|
|
},
|
|
"changeType": {
|
|
"type": "string",
|
|
"enum": ["added", "removed", "modified", "unchanged"],
|
|
"description": "Type of change detected"
|
|
},
|
|
"binaryFormat": {
|
|
"type": "string",
|
|
"enum": ["elf", "pe", "macho", "unknown"],
|
|
"description": "Binary format detected"
|
|
},
|
|
"layerDigest": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
"description": "Layer digest that introduced this file/change"
|
|
},
|
|
"baseHashes": {
|
|
"$ref": "#/$defs/SectionHashSet",
|
|
"description": "Section hashes from base image binary"
|
|
},
|
|
"targetHashes": {
|
|
"$ref": "#/$defs/SectionHashSet",
|
|
"description": "Section hashes from target image binary"
|
|
},
|
|
"sectionDeltas": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/$defs/SectionDelta"
|
|
},
|
|
"description": "Per-section comparison results"
|
|
},
|
|
"confidence": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1,
|
|
"description": "Confidence score for verdict (0.0-1.0)"
|
|
},
|
|
"verdict": {
|
|
"type": "string",
|
|
"enum": ["patched", "vanilla", "unknown", "incompatible"],
|
|
"description": "Classification of the binary change"
|
|
}
|
|
}
|
|
},
|
|
"SectionHashSet": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"buildId": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]+$",
|
|
"description": "GNU Build-ID from .note.gnu.build-id section"
|
|
},
|
|
"fileHash": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$",
|
|
"description": "SHA-256 hash of the entire file"
|
|
},
|
|
"extractorVersion": {
|
|
"type": "string",
|
|
"description": "Version of the section hash extractor"
|
|
},
|
|
"sections": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"$ref": "#/$defs/SectionInfo"
|
|
},
|
|
"description": "Map of section name to section info"
|
|
}
|
|
}
|
|
},
|
|
"SectionInfo": {
|
|
"type": "object",
|
|
"required": ["sha256", "size"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"sha256": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$",
|
|
"description": "SHA-256 hash of section contents"
|
|
},
|
|
"blake3": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$",
|
|
"description": "Optional BLAKE3-256 hash of section contents"
|
|
},
|
|
"size": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Section size in bytes"
|
|
},
|
|
"offset": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Section offset in file"
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"description": "ELF section type (e.g., SHT_PROGBITS)"
|
|
},
|
|
"flags": {
|
|
"type": "string",
|
|
"description": "ELF section flags (e.g., SHF_ALLOC | SHF_EXECINSTR)"
|
|
}
|
|
}
|
|
},
|
|
"SectionDelta": {
|
|
"type": "object",
|
|
"required": ["section", "status"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"section": {
|
|
"type": "string",
|
|
"description": "Section name (e.g., .text, .rodata)",
|
|
"examples": [".text", ".rodata", ".data", ".symtab", ".dynsym"]
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["identical", "modified", "added", "removed"],
|
|
"description": "Section comparison status"
|
|
},
|
|
"baseSha256": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$",
|
|
"description": "SHA-256 of section in base binary"
|
|
},
|
|
"targetSha256": {
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$",
|
|
"description": "SHA-256 of section in target binary"
|
|
},
|
|
"sizeDelta": {
|
|
"type": "integer",
|
|
"description": "Size difference (target - base) in bytes"
|
|
}
|
|
}
|
|
},
|
|
"BinaryDiffMetadata": {
|
|
"type": "object",
|
|
"required": ["toolVersion", "analysisTimestamp"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"toolVersion": {
|
|
"type": "string",
|
|
"description": "Version of the binary diff tool",
|
|
"examples": ["1.0.0", "2026.01.0"]
|
|
},
|
|
"analysisTimestamp": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"description": "UTC timestamp of analysis (ISO-8601)"
|
|
},
|
|
"configDigest": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
"description": "SHA-256 of analysis configuration for reproducibility"
|
|
},
|
|
"totalBinaries": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Total number of binaries analyzed"
|
|
},
|
|
"modifiedBinaries": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Number of binaries with modifications"
|
|
},
|
|
"analyzedSections": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "List of section names analyzed",
|
|
"examples": [[".text", ".rodata", ".data", ".symtab", ".dynsym"]]
|
|
},
|
|
"hashAlgorithms": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["sha256", "blake3"]
|
|
},
|
|
"description": "Hash algorithms used"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"examples": [
|
|
{
|
|
"predicateType": "stellaops.binarydiff.v1",
|
|
"inputs": {
|
|
"base": {
|
|
"reference": "docker://registry.example.com/app:1.0.0",
|
|
"digest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd",
|
|
"platform": {
|
|
"os": "linux",
|
|
"architecture": "amd64"
|
|
}
|
|
},
|
|
"target": {
|
|
"reference": "docker://registry.example.com/app:1.0.1",
|
|
"digest": "sha256:def456abc789012345678901234567890123456789012345678901234567efgh",
|
|
"platform": {
|
|
"os": "linux",
|
|
"architecture": "amd64"
|
|
}
|
|
}
|
|
},
|
|
"findings": [
|
|
{
|
|
"path": "/usr/lib/libssl.so.3",
|
|
"changeType": "modified",
|
|
"binaryFormat": "elf",
|
|
"sectionDeltas": [
|
|
{
|
|
"section": ".text",
|
|
"status": "modified",
|
|
"baseSha256": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
|
|
"targetSha256": "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321",
|
|
"sizeDelta": 256
|
|
},
|
|
{
|
|
"section": ".rodata",
|
|
"status": "identical",
|
|
"baseSha256": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
|
|
"targetSha256": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
|
|
"sizeDelta": 0
|
|
}
|
|
],
|
|
"confidence": 0.95,
|
|
"verdict": "patched"
|
|
}
|
|
],
|
|
"metadata": {
|
|
"toolVersion": "1.0.0",
|
|
"analysisTimestamp": "2026-01-13T12:00:00Z",
|
|
"totalBinaries": 156,
|
|
"modifiedBinaries": 3,
|
|
"analyzedSections": [".text", ".rodata", ".data", ".symtab", ".dynsym"],
|
|
"hashAlgorithms": ["sha256"]
|
|
}
|
|
}
|
|
]
|
|
}
|