5.9 KiB
SPDX 3.0.1 Build Profile Integration
Sprint: SPRINT_20260107_004_003_BE Status: Active Last Updated: 2026-01-08
Overview
The SPDX 3.0.1 Build profile captures provenance information about how an artifact was built. StellaOps integrates this profile with the Attestor module, enabling generation of build attestations that conform to both SPDX 3.0.1 and existing DSSE/in-toto standards.
This creates a unified build provenance format that:
- Aligns with SLSA provenance levels
- Integrates with existing DSSE signing infrastructure
- Can be combined with Software profile SBOMs into single documents
Build Profile Structure
Core Build Element
The Spdx3Build element represents build/CI information:
{
"@type": "Build",
"spdxId": "urn:stellaops:build:abc123",
"build_buildType": "https://stellaops.org/build/container-scan/v1",
"build_buildId": "build-12345",
"build_buildStartTime": "2026-01-07T12:00:00Z",
"build_buildEndTime": "2026-01-07T12:05:00Z",
"build_configSourceUri": ["https://github.com/..."],
"build_configSourceDigest": [{"algorithm": "sha256", "hashValue": "..."}],
"build_configSourceEntrypoint": [".github/workflows/build.yml"],
"build_environment": {"CI": "true"},
"build_parameter": {"target": "release"}
}
Property Mapping
| SLSA/in-toto | SPDX 3.0.1 Build |
|---|---|
| buildType | build_buildType |
| builder.id | CreationInfo.createdBy (Agent) |
| invocation.configSource.uri | build_configSourceUri |
| invocation.configSource.digest | build_configSourceDigest |
| invocation.configSource.entryPoint | build_configSourceEntrypoint |
| invocation.environment | build_environment |
| invocation.parameters | build_parameter |
| metadata.buildStartedOn | build_buildStartTime |
| metadata.buildFinishedOn | build_buildEndTime |
| metadata.buildInvocationId | build_buildId |
API Usage
Mapping Attestations
Use BuildAttestationMapper to convert between SLSA/in-toto and SPDX 3.0.1:
var mapper = new BuildAttestationMapper();
// From in-toto to SPDX 3.0.1
var attestation = new BuildAttestationPayload
{
BuildType = "https://slsa.dev/provenance/v1",
Metadata = new BuildMetadata
{
BuildInvocationId = "run-12345",
BuildStartedOn = DateTimeOffset.UtcNow
}
};
var build = mapper.MapToSpdx3(attestation, "https://stellaops.io/spdx");
// From SPDX 3.0.1 to in-toto
var payload = mapper.MapFromSpdx3(build);
Signing with DSSE
Use DsseSpdx3Signer to sign SPDX 3.0.1 documents:
var signer = new DsseSpdx3Signer(serializer, signingProvider, timeProvider);
var options = new DsseSpdx3SigningOptions
{
PrimaryKeyId = "key-123",
PrimaryAlgorithm = "ES256",
// Optional: Add post-quantum hybrid signature
SecondaryKeyId = "pq-key-456",
SecondaryAlgorithm = "ML-DSA-65"
};
// Sign a Build element
var envelope = await signer.SignBuildProfileAsync(build, null, options);
// Or sign a full document
var envelope = await signer.SignAsync(document, options);
Combined Documents
Use CombinedDocumentBuilder to merge profiles:
var document = CombinedDocumentBuilder.Create(timeProvider)
.WithDocumentId("https://stellaops.io/spdx/combined/12345")
.WithName("Combined SBOM and Build Provenance")
.WithSoftwareProfile(sbom)
.WithBuildProfile(build)
.Build();
// Or use the extension method
var combined = sbom.WithBuildProvenance(
attestation,
documentId: "https://stellaops.io/spdx/combined/12345",
spdxIdPrefix: "https://stellaops.io/spdx");
SLSA Alignment
The SPDX 3.0.1 Build profile supports SLSA provenance levels:
| SLSA Level | SPDX 3.0.1 Support |
|---|---|
| SLSA 1 | Build element with buildType, configSourceUri |
| SLSA 2 | + Signed document (DSSE), builder Agent |
| SLSA 3 | + Hermetic build (environment isolation) |
| SLSA 4 | + Two-party review (external verification) |
Build Relationships
The following relationships connect Build elements to other SPDX elements:
| Relationship | Direction | Description |
|---|---|---|
| GENERATES | Build -> Package | Build produces this artifact |
| GENERATED_FROM | Package -> File | Artifact was built from these sources |
| BUILD_TOOL_OF | Tool -> Build | Tool was used in this build |
Example relationship generation:
var relationships = new BuildRelationshipBuilder(build.SpdxId)
.Generates(packageId)
.GeneratedFrom(sourceFileIds)
.UsedBuildTool(toolId)
.Build();
DSSE Envelope Format
The DSSE envelope wraps the entire SPDX 3.0.1 document:
{
"payloadType": "application/spdx+json",
"payload": "<base64url-encoded SPDX 3.0.1 JSON>",
"signatures": [
{
"keyid": "key-123",
"sig": "<base64url-encoded signature>"
}
]
}
PAE (Pre-Authentication Encoding)
Signatures are computed over the PAE:
DSSEv1 <len(payloadType)> <payloadType> <len(payload)> <payload>
This prevents ambiguity attacks and ensures the payload type is included in the signature.
Verification
To verify a signed SPDX 3.0.1 envelope:
var trustedKeys = new List<DsseVerificationKey>
{
new() { KeyId = "key-123", PublicKey = publicKeyBytes }
};
var isValid = await signer.VerifyAsync(envelope, trustedKeys);
if (isValid)
{
var document = signer.ExtractDocument(envelope);
// Process verified document
}
Offline Support
The Build profile integration supports air-gapped environments:
- All cryptographic operations can use offline key material
- No network calls required for signing or verification
- Documents can be bundled for offline transport
See Attestor Air-Gap Guide for details.