more audit work
This commit is contained in:
213
docs/modules/attestor/build-profile.md
Normal file
213
docs/modules/attestor/build-profile.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# 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:
|
||||
|
||||
```json
|
||||
{
|
||||
"@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:
|
||||
|
||||
```csharp
|
||||
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:
|
||||
|
||||
```csharp
|
||||
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:
|
||||
|
||||
```csharp
|
||||
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:
|
||||
|
||||
```csharp
|
||||
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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```csharp
|
||||
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](./airgap.md) for details.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Attestor Architecture](./architecture.md)
|
||||
- [DSSE Roundtrip Verification](./dsse-roundtrip-verification.md)
|
||||
- [in-toto Link Guide](./intoto-link-guide.md)
|
||||
- [SPDX 3.0.1 Specification](https://spdx.github.io/spdx-spec/v3.0.1/)
|
||||
@@ -81,7 +81,7 @@ The starter policy implements a sensible security posture:
|
||||
### Rule 3: Allow Unreachable
|
||||
|
||||
```yaml
|
||||
- name: ignore-unreachable
|
||||
- name: allow-unreachable
|
||||
description: "Allow unreachable vulnerabilities but log for awareness"
|
||||
match:
|
||||
reachability: unreachable
|
||||
@@ -165,16 +165,14 @@ spec:
|
||||
settings:
|
||||
defaultAction: warn # Never block in dev
|
||||
unknownsThreshold: 0.20 # Allow more unknowns (20%)
|
||||
requireSignedSbom: false
|
||||
requireSignedVerdict: false
|
||||
|
||||
ruleOverrides:
|
||||
- name: block-reachable-high-critical
|
||||
action: warn # Downgrade to warn
|
||||
|
||||
- name: require-signed-sbom-prod
|
||||
enabled: false # Disable signing requirements
|
||||
|
||||
- name: require-signed-verdict-prod
|
||||
enabled: false
|
||||
- name: block-kev
|
||||
action: warn
|
||||
```
|
||||
|
||||
### Staging (`overrides/staging.yaml`)
|
||||
@@ -189,11 +187,10 @@ metadata:
|
||||
|
||||
spec:
|
||||
settings:
|
||||
defaultAction: warn
|
||||
unknownsThreshold: 0.10 # 10% unknowns budget
|
||||
|
||||
ruleOverrides:
|
||||
- name: require-signed-sbom-prod
|
||||
enabled: false # No signing in staging
|
||||
requireSignedSbom: false
|
||||
requireSignedVerdict: false
|
||||
```
|
||||
|
||||
### Production (Default)
|
||||
|
||||
20
docs/modules/router/samples/AGENTS.md
Normal file
20
docs/modules/router/samples/AGENTS.md
Normal file
@@ -0,0 +1,20 @@
|
||||
### Identity
|
||||
You are an autonomous software engineering agent for StellaOps working on Router sample projects in docs.
|
||||
|
||||
### Roles
|
||||
- Document author
|
||||
- Backend developer (.NET 10)
|
||||
- Tester/QA automation engineer
|
||||
|
||||
### Required reading
|
||||
- docs/README.md
|
||||
- docs/07_HIGH_LEVEL_ARCHITECTURE.md
|
||||
- docs/modules/router/architecture.md
|
||||
|
||||
### Working agreements
|
||||
- Scope is limited to `docs/modules/router/samples/**` unless a sprint explicitly allows cross-module edits.
|
||||
- Samples must remain deterministic and ASCII-only; avoid non-ASCII glyphs in logs.
|
||||
- Samples are documentation assets; changes should preserve their instructional value.
|
||||
|
||||
### Testing
|
||||
- Sample projects are not part of the main solution; tests are optional and should be documented if added.
|
||||
222
docs/modules/scanner/pedigree-support.md
Normal file
222
docs/modules/scanner/pedigree-support.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# CycloneDX 1.7 Pedigree Support
|
||||
|
||||
> **Status:** Implementation in progress
|
||||
> **Sprint:** SPRINT_20260107_005_002
|
||||
> **Last Updated:** 2026-01-08
|
||||
|
||||
## Overview
|
||||
|
||||
StellaOps Scanner now supports native CycloneDX 1.7 `component.pedigree.*` fields, enabling detailed representation of component lineage, upstream ancestry, patch history, and commit provenance.
|
||||
|
||||
This integration connects Feedser's backport detection capabilities directly into the SBOM output, providing:
|
||||
|
||||
- **Ancestry tracking**: Links to upstream source packages
|
||||
- **Variant mapping**: Distribution-specific package versions
|
||||
- **Commit provenance**: Security fix commit references
|
||||
- **Patch documentation**: Backport and cherry-pick evidence
|
||||
|
||||
## CycloneDX 1.7 Pedigree Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"type": "library",
|
||||
"name": "openssl",
|
||||
"version": "1.1.1n-0+deb11u5",
|
||||
"purl": "pkg:deb/debian/openssl@1.1.1n-0+deb11u5",
|
||||
"pedigree": {
|
||||
"ancestors": [
|
||||
{
|
||||
"type": "library",
|
||||
"name": "openssl",
|
||||
"version": "1.1.1n",
|
||||
"purl": "pkg:generic/openssl@1.1.1n"
|
||||
}
|
||||
],
|
||||
"variants": [
|
||||
{
|
||||
"type": "library",
|
||||
"name": "openssl",
|
||||
"version": "1.1.1k-9.el9",
|
||||
"purl": "pkg:rpm/rhel/openssl@1.1.1k-9.el9"
|
||||
}
|
||||
],
|
||||
"commits": [
|
||||
{
|
||||
"uid": "abc123def456789",
|
||||
"url": "https://github.com/openssl/openssl/commit/abc123",
|
||||
"message": "Fix CVE-2024-1234"
|
||||
}
|
||||
],
|
||||
"patches": [
|
||||
{
|
||||
"type": "backport",
|
||||
"diff": {
|
||||
"url": "https://salsa.debian.org/...",
|
||||
"text": "--- a/crypto/x509/x509_vfy.c\n+++ b/crypto/x509/x509_vfy.c\n..."
|
||||
},
|
||||
"resolves": [
|
||||
{
|
||||
"type": "security",
|
||||
"id": "CVE-2024-1234",
|
||||
"source": { "name": "NVD" }
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"notes": "Backported security fix from upstream 1.1.1o (CVE-2024-1234). Confidence: 95%. Tier 1 (exact match)."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## API Usage
|
||||
|
||||
### Basic Pedigree Lookup
|
||||
|
||||
```csharp
|
||||
// Inject IPedigreeDataProvider
|
||||
public class SbomEnricher(IPedigreeDataProvider pedigreeProvider)
|
||||
{
|
||||
public async Task EnrichAsync(Component component, CancellationToken ct)
|
||||
{
|
||||
var pedigree = await pedigreeProvider.GetPedigreeAsync(component.Purl, ct);
|
||||
|
||||
if (pedigree is not null)
|
||||
{
|
||||
var mapper = new CycloneDxPedigreeMapper();
|
||||
component.Pedigree = mapper.Map(pedigree);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Pedigree Enrichment
|
||||
|
||||
```csharp
|
||||
// Efficient batch lookup for multiple components
|
||||
var purls = components.Select(c => c.Purl).ToList();
|
||||
var pedigrees = await pedigreeProvider.GetPedigreesBatchAsync(purls, ct);
|
||||
|
||||
foreach (var component in components)
|
||||
{
|
||||
if (pedigrees.TryGetValue(component.Purl, out var data))
|
||||
{
|
||||
component.Pedigree = mapper.Map(data);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Building Pedigree Data Manually
|
||||
|
||||
```csharp
|
||||
// Use builders for custom pedigree construction
|
||||
var ancestorBuilder = new AncestorComponentBuilder();
|
||||
ancestorBuilder
|
||||
.AddGenericUpstream("openssl", "1.1.1n", "https://www.openssl.org")
|
||||
.AddGitHubUpstream("openssl", "openssl", "openssl-1.1.1n");
|
||||
|
||||
var variantBuilder = new VariantComponentBuilder();
|
||||
variantBuilder
|
||||
.AddDebianPackage("openssl", "1.1.1n-0+deb11u5", "bullseye", "amd64")
|
||||
.AddRpmPackage("openssl", "1.1.1k-9.el9", "rhel", "9", "x86_64")
|
||||
.AddAlpinePackage("openssl", "1.1.1t-r2", "3.17");
|
||||
|
||||
var commitBuilder = new CommitInfoBuilder();
|
||||
commitBuilder
|
||||
.AddGitHubCommit("openssl", "openssl", "abc123def", "Fix CVE-2024-1234");
|
||||
|
||||
var patchBuilder = new PatchInfoBuilder();
|
||||
patchBuilder
|
||||
.AddBackport(
|
||||
diffUrl: "https://salsa.debian.org/...",
|
||||
resolvesCves: new[] { "CVE-2024-1234" },
|
||||
source: "debian-security");
|
||||
|
||||
var pedigree = new PedigreeData
|
||||
{
|
||||
Ancestors = ancestorBuilder.Build(),
|
||||
Variants = variantBuilder.Build(),
|
||||
Commits = commitBuilder.Build(),
|
||||
Patches = patchBuilder.Build()
|
||||
};
|
||||
```
|
||||
|
||||
## Feedser Integration
|
||||
|
||||
### Tier Mapping
|
||||
|
||||
| Feedser Tier | Confidence | Description |
|
||||
|--------------|------------|-------------|
|
||||
| Tier 1 | 95-100% | Exact function signature match |
|
||||
| Tier 2 | 80-94% | Changelog/commit message correlation |
|
||||
| Tier 3 | 60-79% | Patch header/context match |
|
||||
| Tier 4 | 40-59% | Binary fingerprint correlation |
|
||||
| Tier 5 | 20-39% | NVD version range heuristic |
|
||||
|
||||
### Patch Origin Mapping
|
||||
|
||||
| Feedser Origin | CycloneDX Patch Type | Description |
|
||||
|----------------|---------------------|-------------|
|
||||
| `upstream` | `cherry-pick` | Direct cherry-pick from upstream |
|
||||
| `distro` | `backport` | Distro-maintained backport |
|
||||
| `vendor` | `unofficial` | Vendor-specific fix |
|
||||
|
||||
## Configuration
|
||||
|
||||
### Scanner Options
|
||||
|
||||
```yaml
|
||||
scanner:
|
||||
sbom:
|
||||
pedigree:
|
||||
enabled: true # Enable pedigree population
|
||||
include_diff: true # Include patch diff text
|
||||
max_diff_size: 50000 # Truncate large diffs
|
||||
cache:
|
||||
enabled: true
|
||||
max_entries: 10000
|
||||
sliding_expiration: 30m
|
||||
absolute_expiration: 4h
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Enable/disable pedigree
|
||||
STELLAOPS_SCANNER_PEDIGREE_ENABLED=true
|
||||
|
||||
# Cache configuration
|
||||
STELLAOPS_PEDIGREE_CACHE_MAX_ENTRIES=10000
|
||||
STELLAOPS_PEDIGREE_CACHE_TTL=4h
|
||||
```
|
||||
|
||||
## Notes Field Format
|
||||
|
||||
The `pedigree.notes` field provides human-readable context:
|
||||
|
||||
```
|
||||
Security patches: 2 backports resolving 3 CVEs.
|
||||
Derived from upstream openssl 1.1.1n.
|
||||
Variants exist for: alpine, debian, rhel.
|
||||
Evidence: confidence 95%, Tier 1 (exact match).
|
||||
Generated: 2026-01-08T12:00:00Z by StellaOps Feedser.
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
1. **Batch lookups**: Use `GetPedigreesBatchAsync` for multiple components to avoid N+1 queries.
|
||||
|
||||
2. **Caching**: The `CachedPedigreeDataProvider` wraps the Feedser client with bounded MemoryCache.
|
||||
|
||||
3. **Negative caching**: Components without pedigree are cached with shorter TTL to reduce repeated lookups.
|
||||
|
||||
4. **Diff truncation**: Large patch diffs are automatically truncated with a link to the full source.
|
||||
|
||||
## See Also
|
||||
|
||||
- [CycloneDX 1.7 Specification - Pedigree](https://cyclonedx.org/docs/1.7/json/#components_items_pedigree)
|
||||
- [Feedser Architecture](../feedser/architecture.md)
|
||||
- [SBOM Generation Guide](./sbom-generation.md)
|
||||
221
docs/modules/vex-lens/security-profile.md
Normal file
221
docs/modules/vex-lens/security-profile.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# SPDX 3.0.1 Security Profile Integration
|
||||
|
||||
> **Sprint:** SPRINT_20260107_004_004_BE
|
||||
> **Status:** Active
|
||||
> **Last Updated:** 2026-01-08
|
||||
|
||||
## Overview
|
||||
|
||||
The SPDX 3.0.1 Security profile captures vulnerability assessment information in a standardized format. StellaOps VexLens integrates this profile to export VEX consensus data in SPDX 3.0.1 format, enabling interoperability with SPDX-compatible tooling.
|
||||
|
||||
This creates a unified security assessment format that:
|
||||
- Aligns with OpenVEX semantics
|
||||
- Integrates with existing SBOM documents
|
||||
- Supports CVSS and EPSS scoring
|
||||
- Enables combined Software+Security profile documents
|
||||
|
||||
## Security Profile Elements
|
||||
|
||||
### Vulnerability Element
|
||||
|
||||
The `Spdx3Vulnerability` element represents a security vulnerability:
|
||||
|
||||
```json
|
||||
{
|
||||
"@type": "security_Vulnerability",
|
||||
"spdxId": "urn:stellaops:vuln:CVE-2026-1234",
|
||||
"name": "CVE-2026-1234",
|
||||
"summary": "Remote code execution in example library",
|
||||
"security_publishedTime": "2026-01-01T00:00:00Z",
|
||||
"security_modifiedTime": "2026-01-05T12:00:00Z",
|
||||
"externalIdentifier": [{
|
||||
"externalIdentifierType": "cve",
|
||||
"identifier": "CVE-2026-1234",
|
||||
"identifierLocator": ["https://nvd.nist.gov/vuln/detail/CVE-2026-1234"]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### VEX Assessment Relationships
|
||||
|
||||
VEX assessments are modeled as relationships between vulnerabilities and products:
|
||||
|
||||
| OpenVEX Status | SPDX 3.0.1 Type | Relationship |
|
||||
|----------------|-----------------|--------------|
|
||||
| affected | VexAffectedVulnAssessmentRelationship | Affects |
|
||||
| not_affected | VexNotAffectedVulnAssessmentRelationship | DoesNotAffect |
|
||||
| fixed | VexFixedVulnAssessmentRelationship | FixedIn |
|
||||
| under_investigation | VexUnderInvestigationVulnAssessmentRelationship | UnderInvestigationFor |
|
||||
|
||||
Example affected assessment:
|
||||
|
||||
```json
|
||||
{
|
||||
"@type": "security_VexAffectedVulnAssessmentRelationship",
|
||||
"spdxId": "urn:stellaops:vex/CVE-2026-1234/pkg-abc",
|
||||
"security_assessedElement": "urn:stellaops:pkg/abc",
|
||||
"from": "urn:stellaops:vuln:CVE-2026-1234",
|
||||
"to": ["urn:stellaops:pkg/abc"],
|
||||
"relationshipType": "affects",
|
||||
"security_vexVersion": "1.0.0",
|
||||
"security_statusNotes": "Vulnerable code path is exposed",
|
||||
"security_actionStatement": "Upgrade to version 2.0.0",
|
||||
"security_actionStatementTime": "2026-01-15T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Justification Types
|
||||
|
||||
For `not_affected` status, SPDX 3.0.1 supports these justification types:
|
||||
|
||||
| OpenVEX Justification | SPDX 3.0.1 JustificationType |
|
||||
|----------------------|------------------------------|
|
||||
| component_not_present | ComponentNotPresent |
|
||||
| vulnerable_code_not_present | VulnerableCodeNotPresent |
|
||||
| vulnerable_code_cannot_be_controlled_by_adversary | VulnerableCodeCannotBeControlledByAdversary |
|
||||
| vulnerable_code_not_in_execute_path | VulnerableCodeNotInExecutePath |
|
||||
| inline_mitigations_already_exist | InlineMitigationsAlreadyExist |
|
||||
|
||||
## API Usage
|
||||
|
||||
### Mapping VEX Consensus
|
||||
|
||||
Use `VexToSpdx3Mapper` to convert VEX consensus to SPDX 3.0.1:
|
||||
|
||||
```csharp
|
||||
var mapper = new VexToSpdx3Mapper(timeProvider);
|
||||
|
||||
var consensus = new VexConsensus
|
||||
{
|
||||
DocumentId = "urn:stellaops:vex:doc-12345",
|
||||
Author = "security-team@example.com",
|
||||
Statements = statements
|
||||
};
|
||||
|
||||
var options = new VexToSpdx3Options
|
||||
{
|
||||
SpdxIdPrefix = "https://stellaops.io/spdx",
|
||||
IncludeCvss = true,
|
||||
IncludeEpss = true,
|
||||
ProductFilter = null // All products
|
||||
};
|
||||
|
||||
var document = await mapper.MapConsensusAsync(consensus, options);
|
||||
```
|
||||
|
||||
### Combined SBOM+VEX Documents
|
||||
|
||||
Use `CombinedSbomVexBuilder` to merge Software and Security profiles:
|
||||
|
||||
```csharp
|
||||
var document = CombinedSbomVexBuilder.Create(timeProvider)
|
||||
.WithDocumentId("https://stellaops.io/spdx/combined/12345")
|
||||
.WithName("Combined SBOM and VEX Data")
|
||||
.WithSoftwareProfile(sbom)
|
||||
.WithSecurityProfile(consensus, spdxIdPrefix)
|
||||
.Build();
|
||||
|
||||
// Or use the extension method
|
||||
var combined = sbom.WithVexData(
|
||||
consensus,
|
||||
documentId: "https://stellaops.io/spdx/combined/12345",
|
||||
spdxIdPrefix: "https://stellaops.io/spdx");
|
||||
```
|
||||
|
||||
### Linked Security Profile
|
||||
|
||||
When combining SBOM and VEX, product IDs (PURLs) are automatically linked to SPDX Package IDs:
|
||||
|
||||
```csharp
|
||||
var combined = CombinedSbomVexBuilder.Create()
|
||||
.WithDocumentId(documentId)
|
||||
.WithSoftwareProfile(sbom) // Extracts PURL->SPDX ID mapping
|
||||
.WithLinkedSecurityProfile(statements, spdxIdPrefix) // Rewrites product IDs
|
||||
.Build();
|
||||
```
|
||||
|
||||
## CVSS Integration
|
||||
|
||||
CVSS v3 scores are mapped to `CvssV3VulnAssessmentRelationship`:
|
||||
|
||||
```json
|
||||
{
|
||||
"@type": "security_CvssV3VulnAssessmentRelationship",
|
||||
"spdxId": "urn:stellaops:cvss/CVE-2026-1234",
|
||||
"security_assessedElement": "urn:stellaops:pkg/abc",
|
||||
"from": "urn:stellaops:vuln:CVE-2026-1234",
|
||||
"to": ["urn:stellaops:pkg/abc"],
|
||||
"security_score": 9.8,
|
||||
"security_severity": "Critical",
|
||||
"security_vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
|
||||
}
|
||||
```
|
||||
|
||||
Severity is automatically calculated from score:
|
||||
- 0.0: None
|
||||
- 0.1-3.9: Low
|
||||
- 4.0-6.9: Medium
|
||||
- 7.0-8.9: High
|
||||
- 9.0-10.0: Critical
|
||||
|
||||
## EPSS Integration
|
||||
|
||||
EPSS (Exploit Prediction Scoring System) data is mapped to `EpssVulnAssessmentRelationship`:
|
||||
|
||||
```json
|
||||
{
|
||||
"@type": "security_EpssVulnAssessmentRelationship",
|
||||
"spdxId": "urn:stellaops:epss/CVE-2026-1234",
|
||||
"security_assessedElement": "urn:stellaops:pkg/abc",
|
||||
"from": "urn:stellaops:vuln:CVE-2026-1234",
|
||||
"to": ["urn:stellaops:pkg/abc"],
|
||||
"security_probability": 0.85,
|
||||
"security_percentile": 0.97
|
||||
}
|
||||
```
|
||||
|
||||
## Parsing Security Profile
|
||||
|
||||
The `Spdx3Parser` can parse SPDX 3.0.1 documents containing Security profile elements:
|
||||
|
||||
```csharp
|
||||
var parser = new Spdx3Parser(contextResolver, logger);
|
||||
var result = await parser.ParseAsync(stream);
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
var vulnerabilities = result.Document.Elements
|
||||
.OfType<Spdx3Vulnerability>();
|
||||
|
||||
var vexAssessments = result.Document.Relationships
|
||||
.OfType<Spdx3VulnAssessmentRelationship>();
|
||||
}
|
||||
```
|
||||
|
||||
## OpenVEX Interoperability
|
||||
|
||||
VexLens maintains full interoperability between OpenVEX and SPDX 3.0.1:
|
||||
|
||||
| Feature | OpenVEX | SPDX 3.0.1 Security |
|
||||
|---------|---------|---------------------|
|
||||
| Status values | 4 statuses | 4 relationship types |
|
||||
| Justifications | 5 types | 5 justification types |
|
||||
| Action statements | Supported | Supported |
|
||||
| Timestamps | Supported | Supported |
|
||||
| CVSS | Embedded | Separate relationship |
|
||||
| EPSS | Custom extension | Separate relationship |
|
||||
|
||||
## Offline Support
|
||||
|
||||
The Security profile integration supports air-gapped environments:
|
||||
|
||||
- All mapping operations are local
|
||||
- No network calls required for document generation
|
||||
- Documents can be bundled for offline transport
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [VexLens Architecture](./architecture.md)
|
||||
- [OpenVEX Guide](../../VEX_CONSENSUS_GUIDE.md)
|
||||
- [Attestor Build Profile](../attestor/build-profile.md)
|
||||
- [SPDX 3.0.1 Specification](https://spdx.github.io/spdx-spec/v3.0.1/)
|
||||
Reference in New Issue
Block a user