Resolve Concelier/Excititor merge conflicts
This commit is contained in:
6
samples/TASKS.md
Normal file
6
samples/TASKS.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Samples Task Board
|
||||
|
||||
| ID | Status | Owner(s) | Depends on | Description | Exit Criteria |
|
||||
|----|--------|----------|------------|-------------|---------------|
|
||||
| SAMPLES-10-001 | DONE | Samples Guild, Scanner Team | SCANNER-EMIT-10-605 | Curate sample images (nginx, alpine+busybox, distroless+go, .NET AOT, python venv, npm monorepo) with expected SBOM/BOM-Index sidecars. | Samples committed under `samples/`; golden SBOM/BOM-Index files present; documented usage. |
|
||||
| SAMPLES-13-004 | TODO | Samples Guild, Policy Guild | POLICY-CORE-09-006, UI-POLICY-13-007 | Add policy preview/report fixtures showing confidence bands and unknown-age tags. | Confidence sample (`samples/policy/policy-preview-unknown.json`) reviewed, documented usage in UI dev guide, ajv validation hook updated. |
|
||||
52
samples/api/reports/report-sample.dsse.json
Normal file
52
samples/api/reports/report-sample.dsse.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"report": {
|
||||
"reportId": "report-3def5f362aa475ef14b6",
|
||||
"imageDigest": "sha256:deadbeef",
|
||||
"generatedAt": "2025-10-19T08:28:09.3699267+00:00",
|
||||
"verdict": "blocked",
|
||||
"policy": {
|
||||
"revisionId": "rev-1",
|
||||
"digest": "27d2ec2b34feedc304fc564d252ecee1c8fa14ea581a5ff5c1ea8963313d5c8d"
|
||||
},
|
||||
"summary": {
|
||||
"total": 1,
|
||||
"blocked": 1,
|
||||
"warned": 0,
|
||||
"ignored": 0,
|
||||
"quieted": 0
|
||||
},
|
||||
"verdicts": [
|
||||
{
|
||||
"findingId": "finding-1",
|
||||
"status": "Blocked",
|
||||
"ruleName": "Block Critical",
|
||||
"ruleAction": "Block",
|
||||
"score": 40.5,
|
||||
"configVersion": "1.0",
|
||||
"inputs": {
|
||||
"reachabilityWeight": 0.45,
|
||||
"baseScore": 40.5,
|
||||
"severityWeight": 90,
|
||||
"trustWeight": 1,
|
||||
"trustWeight.NVD": 1,
|
||||
"reachability.runtime": 0.45
|
||||
},
|
||||
"quiet": false,
|
||||
"sourceTrust": "NVD",
|
||||
"reachability": "runtime"
|
||||
}
|
||||
],
|
||||
"issues": []
|
||||
},
|
||||
"dsse": {
|
||||
"payloadType": "application/vnd.stellaops.report+json",
|
||||
"payload": "eyJyZXBvcnRJZCI6InJlcG9ydC0zZGVmNWYzNjJhYTQ3NWVmMTRiNiIsImltYWdlRGlnZXN0Ijoic2hhMjU2OmRlYWRiZWVmIiwiZ2VuZXJhdGVkQXQiOiIyMDI1LTEwLTE5VDA4OjI4OjA5LjM2OTkyNjcrMDA6MDAiLCJ2ZXJkaWN0IjoiYmxvY2tlZCIsInBvbGljeSI6eyJyZXZpc2lvbklkIjoicmV2LTEiLCJkaWdlc3QiOiIyN2QyZWMyYjM0ZmVlZGMzMDRmYzU2NGQyNTJlY2VlMWM4ZmExNGVhNTgxYTVmZjVjMWVhODk2MzMxM2Q1YzhkIn0sInN1bW1hcnkiOnsidG90YWwiOjEsImJsb2NrZWQiOjEsIndhcm5lZCI6MCwiaWdub3JlZCI6MCwicXVpZXRlZCI6MH0sInZlcmRpY3RzIjpbeyJmaW5kaW5nSWQiOiJmaW5kaW5nLTEiLCJzdGF0dXMiOiJCbG9ja2VkIiwicnVsZU5hbWUiOiJCbG9jayBDcml0aWNhbCIsInJ1bGVBY3Rpb24iOiJCbG9jayIsInNjb3JlIjo0MC41LCJjb25maWdWZXJzaW9uIjoiMS4wIiwiaW5wdXRzIjp7InJlYWNoYWJpbGl0eVdlaWdodCI6MC40NSwiYmFzZVNjb3JlIjo0MC41LCJzZXZlcml0eVdlaWdodCI6OTAsInRydXN0V2VpZ2h0IjoxLCJ0cnVzdFdlaWdodC5OVkQiOjEsInJlYWNoYWJpbGl0eS5ydW50aW1lIjowLjQ1fSwicXVpZXQiOmZhbHNlLCJzb3VyY2VUcnVzdCI6Ik5WRCIsInJlYWNoYWJpbGl0eSI6InJ1bnRpbWUifV0sImlzc3VlcyI6W119",
|
||||
"signatures": [
|
||||
{
|
||||
"keyId": "scanner-report-signing",
|
||||
"algorithm": "hs256",
|
||||
"signature": "s3qnWeRsYs+QA/nO84Us8G2xjZcvphc2P7KnOdTVwQs="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
19
samples/api/scheduler/audit.json
Normal file
19
samples/api/scheduler/audit.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "audit_169754",
|
||||
"tenantId": "tenant-alpha",
|
||||
"category": "scheduler",
|
||||
"action": "pause",
|
||||
"occurredAt": "2025-10-18T22:10:00+00:00",
|
||||
"actor": {
|
||||
"actorId": "user_admin",
|
||||
"displayName": "Cluster Admin",
|
||||
"kind": "user"
|
||||
},
|
||||
"scheduleId": "sch_20251018a",
|
||||
"correlationId": "corr-123",
|
||||
"metadata": {
|
||||
"details": "schedule paused",
|
||||
"reason": "maintenance"
|
||||
},
|
||||
"message": "Paused via API"
|
||||
}
|
||||
34
samples/api/scheduler/impact-set.json
Normal file
34
samples/api/scheduler/impact-set.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"schemaVersion": "scheduler.impact-set@1",
|
||||
"selector": {
|
||||
"scope": "all-images",
|
||||
"tenantId": "tenant-alpha",
|
||||
"namespaces": [],
|
||||
"repositories": [],
|
||||
"digests": [],
|
||||
"includeTags": [],
|
||||
"labels": [],
|
||||
"resolvesTags": false
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"imageDigest": "sha256:f1e2d3",
|
||||
"registry": "registry.internal",
|
||||
"repository": "app/api",
|
||||
"namespaces": [
|
||||
"team-a"
|
||||
],
|
||||
"tags": [
|
||||
"prod"
|
||||
],
|
||||
"usedByEntrypoint": true,
|
||||
"labels": {
|
||||
"env": "prod"
|
||||
}
|
||||
}
|
||||
],
|
||||
"usageOnly": true,
|
||||
"generatedAt": "2025-10-18T22:02:58+00:00",
|
||||
"total": 412,
|
||||
"snapshotId": "impact-20251018-1"
|
||||
}
|
||||
50
samples/api/scheduler/run.json
Normal file
50
samples/api/scheduler/run.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"schemaVersion": "scheduler.run@1",
|
||||
"id": "run_20251018_0001",
|
||||
"tenantId": "tenant-alpha",
|
||||
"scheduleId": "sch_20251018a",
|
||||
"trigger": "feedser",
|
||||
"state": "running",
|
||||
"stats": {
|
||||
"candidates": 1280,
|
||||
"deduped": 910,
|
||||
"queued": 624,
|
||||
"completed": 310,
|
||||
"deltas": 42,
|
||||
"newCriticals": 7,
|
||||
"newHigh": 11,
|
||||
"newMedium": 18,
|
||||
"newLow": 6
|
||||
},
|
||||
"reason": {
|
||||
"feedserExportId": "exp-20251018-03"
|
||||
},
|
||||
"createdAt": "2025-10-18T22:03:14+00:00",
|
||||
"startedAt": "2025-10-18T22:03:20+00:00",
|
||||
"deltas": [
|
||||
{
|
||||
"imageDigest": "sha256:a1b2c3",
|
||||
"newFindings": 3,
|
||||
"newCriticals": 1,
|
||||
"newHigh": 1,
|
||||
"newMedium": 1,
|
||||
"newLow": 0,
|
||||
"kevHits": [
|
||||
"CVE-2025-0002"
|
||||
],
|
||||
"topFindings": [
|
||||
{
|
||||
"purl": "pkg:rpm/openssl@3.0.12-5.el9",
|
||||
"vulnerabilityId": "CVE-2025-0002",
|
||||
"severity": "critical",
|
||||
"link": "https://ui.internal/scans/sha256:a1b2c3"
|
||||
}
|
||||
],
|
||||
"attestation": {
|
||||
"uuid": "rekor-314",
|
||||
"verified": true
|
||||
},
|
||||
"detectedAt": "2025-10-18T22:03:21+00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
57
samples/api/scheduler/schedule.json
Normal file
57
samples/api/scheduler/schedule.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"schemaVersion": "scheduler.schedule@1",
|
||||
"id": "sch_20251018a",
|
||||
"tenantId": "tenant-alpha",
|
||||
"name": "Nightly Prod",
|
||||
"enabled": true,
|
||||
"cronExpression": "0 2 * * *",
|
||||
"timezone": "UTC",
|
||||
"mode": "analysis-only",
|
||||
"selection": {
|
||||
"scope": "by-namespace",
|
||||
"tenantId": "tenant-alpha",
|
||||
"namespaces": [
|
||||
"team-a",
|
||||
"team-b"
|
||||
],
|
||||
"repositories": [
|
||||
"app/service-api"
|
||||
],
|
||||
"digests": [],
|
||||
"includeTags": [
|
||||
"canary",
|
||||
"prod"
|
||||
],
|
||||
"labels": [
|
||||
{
|
||||
"key": "env",
|
||||
"values": [
|
||||
"prod",
|
||||
"staging"
|
||||
]
|
||||
}
|
||||
],
|
||||
"resolvesTags": true
|
||||
},
|
||||
"onlyIf": {
|
||||
"lastReportOlderThanDays": 7,
|
||||
"policyRevision": "policy@42"
|
||||
},
|
||||
"notify": {
|
||||
"onNewFindings": true,
|
||||
"minSeverity": "high",
|
||||
"includeKev": true
|
||||
},
|
||||
"limits": {
|
||||
"maxJobs": 1000,
|
||||
"ratePerSecond": 25,
|
||||
"parallelism": 4
|
||||
},
|
||||
"subscribers": [
|
||||
"notify.ops"
|
||||
],
|
||||
"createdAt": "2025-10-18T22:00:00+00:00",
|
||||
"createdBy": "svc_scheduler",
|
||||
"updatedAt": "2025-10-18T22:00:00+00:00",
|
||||
"updatedBy": "svc_scheduler"
|
||||
}
|
||||
4
samples/ci/buildx-demo/Dockerfile
Normal file
4
samples/ci/buildx-demo/Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
||||
FROM alpine:3.20
|
||||
RUN adduser -S stella && echo "hello" > /app.txt
|
||||
USER stella
|
||||
CMD ["/bin/sh","-c","cat /app.txt"]
|
||||
42
samples/ci/buildx-demo/README.md
Normal file
42
samples/ci/buildx-demo/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Buildx SBOM Demo Workflow
|
||||
|
||||
This sample GitHub Actions workflow shows how to run the StellaOps BuildX generator alongside a container build.
|
||||
|
||||
## What it does
|
||||
|
||||
1. Publishes the `StellaOps.Scanner.Sbomer.BuildXPlugin` with the manifest copied beside the binaries.
|
||||
2. Calls the plug-in `handshake` command to verify the local CAS directory.
|
||||
3. Builds a tiny Alpine-based image via `docker buildx`.
|
||||
4. Generates a CycloneDX SBOM from the built image with `docker sbom`.
|
||||
5. Emits a descriptor + provenance placeholder referencing the freshly generated SBOM with the `descriptor` command.
|
||||
6. Sends the placeholder to a mock Attestor endpoint and uploads the descriptor, SBOM, and captured request as artefacts. (Swap the mock step with your real Attestor URL + `STELLAOPS_ATTESTOR_TOKEN` secret when ready.)
|
||||
|
||||
## Files
|
||||
|
||||
- `github-actions-buildx-demo.yml` – workflow definition (`workflow_dispatch` + `demo/buildx` branch trigger).
|
||||
- `Dockerfile` – minimal demo image.
|
||||
- `github-actions-buildx-demo.yml` now captures a real SBOM via `docker sbom`.
|
||||
|
||||
## Running locally
|
||||
|
||||
```bash
|
||||
dotnet publish src/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj -c Release -o out/buildx
|
||||
|
||||
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \
|
||||
--manifest out/buildx \
|
||||
--cas out/cas
|
||||
|
||||
docker buildx build --load -t stellaops/buildx-demo:ci samples/ci/buildx-demo
|
||||
DIGEST=$(docker image inspect stellaops/buildx-demo:ci --format '{{index .RepoDigests 0}}')
|
||||
|
||||
docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json
|
||||
|
||||
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \
|
||||
--manifest out/buildx \
|
||||
--image "$DIGEST" \
|
||||
--sbom out/buildx-sbom.cdx.json \
|
||||
--sbom-name buildx-sbom.cdx.json \
|
||||
> out/buildx-descriptor.json
|
||||
```
|
||||
|
||||
The descriptor JSON contains deterministic annotations and provenance placeholders ready for the Attestor.
|
||||
153
samples/ci/buildx-demo/github-actions-buildx-demo.yml
Normal file
153
samples/ci/buildx-demo/github-actions-buildx-demo.yml
Normal file
@@ -0,0 +1,153 @@
|
||||
name: Buildx SBOM Demo
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ demo/buildx ]
|
||||
|
||||
jobs:
|
||||
buildx-sbom:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set up .NET 10 preview
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
|
||||
- name: Publish StellaOps BuildX generator
|
||||
run: |
|
||||
dotnet publish src/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj \
|
||||
-c Release \
|
||||
-o out/buildx
|
||||
|
||||
- name: Handshake CAS
|
||||
run: |
|
||||
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \
|
||||
--manifest out/buildx \
|
||||
--cas out/cas
|
||||
|
||||
- name: Build demo container image
|
||||
run: |
|
||||
docker buildx build --load -t stellaops/buildx-demo:ci samples/ci/buildx-demo
|
||||
|
||||
- name: Capture image digest
|
||||
id: digest
|
||||
run: |
|
||||
DIGEST=$(docker image inspect stellaops/buildx-demo:ci --format '{{index .RepoDigests 0}}')
|
||||
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Generate SBOM from built image
|
||||
run: |
|
||||
mkdir -p out
|
||||
docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json
|
||||
|
||||
- name: Start mock Attestor
|
||||
id: attestor
|
||||
run: |
|
||||
mkdir -p out
|
||||
cat <<'PY' > out/mock-attestor.py
|
||||
import json
|
||||
import os
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
length = int(self.headers.get('Content-Length') or 0)
|
||||
body = self.rfile.read(length)
|
||||
with open(os.path.join('out', 'provenance-request.json'), 'wb') as fp:
|
||||
fp.write(body)
|
||||
self.send_response(202)
|
||||
self.end_headers()
|
||||
self.wfile.write(b'accepted')
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
server = HTTPServer(('127.0.0.1', 8085), Handler)
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
server.server_close()
|
||||
PY
|
||||
touch out/provenance-request.json
|
||||
python3 out/mock-attestor.py &
|
||||
echo $! > out/mock-attestor.pid
|
||||
|
||||
- name: Emit descriptor with provenance placeholder
|
||||
env:
|
||||
IMAGE_DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
# Uncomment the next line and remove the mock Attestor block to hit a real service.
|
||||
# STELLAOPS_ATTESTOR_TOKEN: ${{ secrets.STELLAOPS_ATTESTOR_TOKEN }}
|
||||
run: |
|
||||
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \
|
||||
--manifest out/buildx \
|
||||
--image "$IMAGE_DIGEST" \
|
||||
--sbom out/buildx-sbom.cdx.json \
|
||||
--sbom-name buildx-sbom.cdx.json \
|
||||
--artifact-type application/vnd.stellaops.sbom.layer+json \
|
||||
--sbom-format cyclonedx-json \
|
||||
--sbom-kind inventory \
|
||||
--repository ${{ github.repository }} \
|
||||
--build-ref ${{ github.sha }} \
|
||||
--attestor http://127.0.0.1:8085/provenance \
|
||||
> out/buildx-descriptor.json
|
||||
|
||||
- name: Verify descriptor determinism
|
||||
env:
|
||||
IMAGE_DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
run: |
|
||||
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \
|
||||
--manifest out/buildx \
|
||||
--image "$IMAGE_DIGEST" \
|
||||
--sbom out/buildx-sbom.cdx.json \
|
||||
--sbom-name buildx-sbom.cdx.json \
|
||||
--artifact-type application/vnd.stellaops.sbom.layer+json \
|
||||
--sbom-format cyclonedx-json \
|
||||
--sbom-kind inventory \
|
||||
--repository ${{ github.repository }} \
|
||||
--build-ref ${{ github.sha }} \
|
||||
> out/buildx-descriptor-repeat.json
|
||||
|
||||
python - <<'PY'
|
||||
import json
|
||||
|
||||
def normalize(path: str) -> dict:
|
||||
with open(path, 'r', encoding='utf-8') as handle:
|
||||
data = json.load(handle)
|
||||
data.pop('generatedAt', None)
|
||||
return data
|
||||
|
||||
baseline = normalize('out/buildx-descriptor.json')
|
||||
repeat = normalize('out/buildx-descriptor-repeat.json')
|
||||
|
||||
if baseline != repeat:
|
||||
raise SystemExit('Descriptor output changed between runs.')
|
||||
PY
|
||||
|
||||
- name: Stop mock Attestor
|
||||
if: always()
|
||||
run: |
|
||||
if [ -f out/mock-attestor.pid ]; then
|
||||
kill $(cat out/mock-attestor.pid)
|
||||
fi
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: stellaops-buildx-demo
|
||||
path: |
|
||||
out/buildx-descriptor.json
|
||||
out/buildx-sbom.cdx.json
|
||||
out/provenance-request.json
|
||||
out/buildx-descriptor-repeat.json
|
||||
|
||||
- name: Show descriptor summary
|
||||
run: |
|
||||
cat out/buildx-descriptor.json
|
||||
98
samples/policy/policy-preview-unknown.json
Normal file
98
samples/policy/policy-preview-unknown.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"previewRequest": {
|
||||
"imageDigest": "sha256:7dbe0c9a5d4f1c8184007e9d94dbe55928f8a2db5ab9c1c2d4a2f7bbcdfe1234",
|
||||
"findings": [
|
||||
{
|
||||
"id": "library:pkg/openssl@1.1.1w",
|
||||
"severity": "Unknown",
|
||||
"source": "NVD",
|
||||
"tags": [
|
||||
"trust:vendor",
|
||||
"reachability:unknown",
|
||||
"unknown-age-days:5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "library:pkg/zlib@1.3.1",
|
||||
"severity": "High",
|
||||
"source": "NVD",
|
||||
"tags": [
|
||||
"state:unknown",
|
||||
"reachability:runtime",
|
||||
"unknown-since:2025-10-10T00:00:00Z",
|
||||
"observed-at:2025-10-19T12:00:00Z"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"previewResponse": {
|
||||
"success": true,
|
||||
"policyDigest": "8a0f72f8dc5c51c46991db3bba34e9b3c0c8e944a7a6d0a9c29a9aa6b8439876",
|
||||
"revisionId": "rev-42",
|
||||
"changed": 2,
|
||||
"diffs": [
|
||||
{
|
||||
"findingId": "library:pkg/openssl@1.1.1w",
|
||||
"baseline": {
|
||||
"findingId": "library:pkg/openssl@1.1.1w",
|
||||
"status": "Pass",
|
||||
"score": 0,
|
||||
"configVersion": "1.0"
|
||||
},
|
||||
"projected": {
|
||||
"findingId": "library:pkg/openssl@1.1.1w",
|
||||
"status": "Blocked",
|
||||
"ruleName": "Block vendor unknowns",
|
||||
"ruleAction": "block",
|
||||
"score": 19.5,
|
||||
"configVersion": "1.0",
|
||||
"inputs": {
|
||||
"severityWeight": 50,
|
||||
"trustWeight": 0.65,
|
||||
"reachabilityWeight": 0.6,
|
||||
"baseScore": 19.5,
|
||||
"trustWeight.vendor": 0.65,
|
||||
"reachability.unknown": 0.6,
|
||||
"unknownConfidence": 0.55,
|
||||
"unknownAgeDays": 5
|
||||
},
|
||||
"unknownConfidence": 0.55,
|
||||
"confidenceBand": "medium",
|
||||
"unknownAgeDays": 5
|
||||
},
|
||||
"changed": true
|
||||
},
|
||||
{
|
||||
"findingId": "library:pkg/zlib@1.3.1",
|
||||
"baseline": {
|
||||
"findingId": "library:pkg/zlib@1.3.1",
|
||||
"status": "Pass",
|
||||
"score": 0,
|
||||
"configVersion": "1.0"
|
||||
},
|
||||
"projected": {
|
||||
"findingId": "library:pkg/zlib@1.3.1",
|
||||
"status": "Warned",
|
||||
"ruleName": "Runtime mitigation required",
|
||||
"ruleAction": "warn",
|
||||
"score": 33.75,
|
||||
"configVersion": "1.0",
|
||||
"inputs": {
|
||||
"severityWeight": 75,
|
||||
"trustWeight": 1,
|
||||
"reachabilityWeight": 0.45,
|
||||
"baseScore": 33.75,
|
||||
"reachability.runtime": 0.45,
|
||||
"warnPenalty": 15,
|
||||
"unknownConfidence": 0.35,
|
||||
"unknownAgeDays": 9
|
||||
},
|
||||
"unknownConfidence": 0.35,
|
||||
"confidenceBand": "medium",
|
||||
"unknownAgeDays": 9
|
||||
},
|
||||
"changed": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
6
samples/runtime/README.md
Normal file
6
samples/runtime/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Runtime Fixtures
|
||||
|
||||
Supporting filesystem snippets consumed by analyzer microbenchmarks and integration tests. They are intentionally lightweight yet deterministic so they can be committed to the repository without bloating history.
|
||||
|
||||
- `npm-monorepo/` – trimmed `node_modules/` tree for workspace-style Node.js projects.
|
||||
- `python-venv/` – selected `site-packages/` entries highlighting `*.dist-info` metadata.
|
||||
9
samples/runtime/npm-monorepo/README.md
Normal file
9
samples/runtime/npm-monorepo/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# NPM Monorepo Fixture
|
||||
|
||||
This fixture represents a trimmed monorepo layout used by the analyzer microbench. It contains four packages under `node_modules/` with realistic metadata and dependency edges.
|
||||
|
||||
- `@stella/core` depends on `lodash`.
|
||||
- `@stella/web` depends on `@stella/core` and `rxjs`.
|
||||
- Third-party packages expose standard `name`, `version`, and `license` fields.
|
||||
|
||||
The files are intentionally small so that the bench harness focuses on directory traversal and metadata parsing overhead.
|
||||
9
samples/runtime/npm-monorepo/node_modules/@stella/core/package.json
generated
vendored
Normal file
9
samples/runtime/npm-monorepo/node_modules/@stella/core/package.json
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@stella/core",
|
||||
"version": "2.0.0",
|
||||
"description": "Core services shared by the sample monorepo.",
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
10
samples/runtime/npm-monorepo/node_modules/@stella/web/package.json
generated
vendored
Normal file
10
samples/runtime/npm-monorepo/node_modules/@stella/web/package.json
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@stella/web",
|
||||
"version": "1.5.3",
|
||||
"description": "Web layer in the sample monorepo.",
|
||||
"dependencies": {
|
||||
"@stella/core": "2.0.0",
|
||||
"rxjs": "7.8.1"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
6
samples/runtime/npm-monorepo/node_modules/lodash/package.json
generated
vendored
Normal file
6
samples/runtime/npm-monorepo/node_modules/lodash/package.json
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "lodash",
|
||||
"version": "4.17.21",
|
||||
"description": "Lodash modular utilities.",
|
||||
"license": "MIT"
|
||||
}
|
||||
6
samples/runtime/npm-monorepo/node_modules/rxjs/package.json
generated
vendored
Normal file
6
samples/runtime/npm-monorepo/node_modules/rxjs/package.json
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "rxjs",
|
||||
"version": "7.8.1",
|
||||
"description": "Reactive Extensions for modern JavaScript.",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
5
samples/runtime/python-venv/README.md
Normal file
5
samples/runtime/python-venv/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Python Virtual Environment Fixture
|
||||
|
||||
The fixture mimics a trimmed `site-packages/` layout with three common dependencies (`requests`, `urllib3`, `certifi`). Each package exposes a `*.dist-info/METADATA` file so the analyzer bench can validate parsing performance and header extraction.
|
||||
|
||||
Files intentionally omit wheels and bytecode to keep the tree compact while still realistic.
|
||||
@@ -0,0 +1,5 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: certifi
|
||||
Version: 2024.6.2
|
||||
Summary: Mozilla SSL Certificates.
|
||||
License: MPL-2.0
|
||||
@@ -0,0 +1,7 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: requests
|
||||
Version: 2.32.0
|
||||
Summary: Python HTTP for Humans.
|
||||
License: Apache-2.0
|
||||
Requires-Dist: urllib3 (>=1.21.1,<3)
|
||||
Requires-Dist: certifi (>=2017.4.17)
|
||||
@@ -0,0 +1,5 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: urllib3
|
||||
Version: 2.2.1
|
||||
Summary: HTTP library with thread-safe connection pooling.
|
||||
License: MIT
|
||||
12
samples/scanner/README.md
Normal file
12
samples/scanner/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Scanner Samples
|
||||
|
||||
Curated SBOM and BOM Index fixtures covering representative container types referenced throughout Sprint 10. Each sample folder under `images/` corresponds to a container profile, while `../runtime` holds trimmed filesystem fixtures used by analyzer and perf tests.
|
||||
|
||||
| Sample | Highlights |
|
||||
| ------ | ---------- |
|
||||
| `nginx` | Alpine packages with mixed inventory/runtime coverage. |
|
||||
| `alpine-busybox` | Minimal BusyBox rootfs with musl runtime linkage. |
|
||||
| `distroless-go` | Go binary with Distroless base and Go build-info evidence. |
|
||||
| `dotnet-aot` | Ahead-of-time compiled .NET worker exposing NuGet dependencies. |
|
||||
| `python-venv` | Python virtualenv with `*.dist-info` evidence. |
|
||||
| `npm-monorepo` | Node workspace packages resolved via `package.json`. |
|
||||
3
samples/scanner/images/alpine-busybox/README.md
Normal file
3
samples/scanner/images/alpine-busybox/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Alpine + BusyBox Sample
|
||||
|
||||
Fixtures showcase the tiny Alpine image that powers many minimal containers. BusyBox and musl appear in usage because they back the entrypoint shell, while alpine-baselayout remains inventory-only.
|
||||
42
samples/scanner/images/alpine-busybox/bom-index.json
Normal file
42
samples/scanner/images/alpine-busybox/bom-index.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "docker.io/library/alpine",
|
||||
"digest": "sha256:9a214327ec7df5bc8f1d3f12171873be7d778fdbf473d6f9a63d5de6c6bfb2d3",
|
||||
"tag": "3.20"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:apk/alpine/busybox@1.36.1-r2?arch=x86_64",
|
||||
"layerDigest": "sha256:5555555555555555555555555555555555555555555555555555555555555555",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["GPL-2.0-only"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:apk/alpine/musl@1.2.5-r0?arch=x86_64",
|
||||
"layerDigest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:apk/alpine/alpine-baselayout@3.4.3-r0?arch=x86_64",
|
||||
"layerDigest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["GPL-2.0-only"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
34
samples/scanner/images/alpine-busybox/inventory.cdx.json
Normal file
34
samples/scanner/images/alpine-busybox/inventory.cdx.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "alpine-busybox",
|
||||
"version": "3.20",
|
||||
"bomRef": "pkg:docker/library/alpine@sha256:9a214327ec7df5bc8f1d3f12171873be7d778fdbf473d6f9a63d5de6c6bfb2d3"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:apk/alpine/busybox@1.36.1-r2?arch=x86_64",
|
||||
"name": "busybox",
|
||||
"version": "1.36.1-r2"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/musl@1.2.5-r0?arch=x86_64",
|
||||
"name": "musl",
|
||||
"version": "1.2.5-r0"
|
||||
},
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:apk/alpine/alpine-baselayout@3.4.3-r0?arch=x86_64",
|
||||
"name": "alpine-baselayout",
|
||||
"version": "3.4.3-r0"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
samples/scanner/images/alpine-busybox/usage.cdx.json
Normal file
28
samples/scanner/images/alpine-busybox/usage.cdx.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "alpine-busybox",
|
||||
"version": "3.20",
|
||||
"bomRef": "pkg:docker/library/alpine@sha256:9a214327ec7df5bc8f1d3f12171873be7d778fdbf473d6f9a63d5de6c6bfb2d3"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:apk/alpine/busybox@1.36.1-r2?arch=x86_64",
|
||||
"name": "busybox",
|
||||
"version": "1.36.1-r2"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/musl@1.2.5-r0?arch=x86_64",
|
||||
"name": "musl",
|
||||
"version": "1.2.5-r0"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
samples/scanner/images/distroless-go/README.md
Normal file
3
samples/scanner/images/distroless-go/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Distroless + Go Sample
|
||||
|
||||
Demonstrates a Go binary shipped on top of Distroless. Only the compiled service appears in the usage SBOM, while the Go standard library remains inventory-only and still tracked in the BOM Index.
|
||||
32
samples/scanner/images/distroless-go/bom-index.json
Normal file
32
samples/scanner/images/distroless-go/bom-index.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "gcr.io/distroless/base",
|
||||
"digest": "sha256:0dd2f0f15c9f8abfba6a0ce0d7d6a24e2e1071c977733f6e77cbe51b87f15ad9",
|
||||
"tag": "nonroot"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:golang/github.com/stellaops/sample-service@v1.4.0",
|
||||
"layerDigest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["Apache-2.0"],
|
||||
"evidence": {
|
||||
"kind": "go-buildinfo",
|
||||
"path": "/workspace/service"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:golang/std@go1.22.5",
|
||||
"layerDigest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["BSD-3-Clause"],
|
||||
"evidence": {
|
||||
"kind": "go-buildinfo",
|
||||
"path": "/workspace/service"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
34
samples/scanner/images/distroless-go/inventory.cdx.json
Normal file
34
samples/scanner/images/distroless-go/inventory.cdx.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "distroless-go",
|
||||
"version": "2025.10.0",
|
||||
"bomRef": "pkg:docker/gcr.io/distroless/base@sha256:0dd2f0f15c9f8abfba6a0ce0d7d6a24e2e1071c977733f6e77cbe51b87f15ad9"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:golang/github.com/stellaops/sample-service@v1.4.0",
|
||||
"name": "github.com/stellaops/sample-service",
|
||||
"version": "v1.4.0",
|
||||
"properties": [
|
||||
{
|
||||
"name": "stellaops.entrypoint",
|
||||
"value": "/workspace/service"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:golang/std@go1.22.5",
|
||||
"name": "golang-stdlib",
|
||||
"version": "go1.22.5"
|
||||
}
|
||||
]
|
||||
}
|
||||
22
samples/scanner/images/distroless-go/usage.cdx.json
Normal file
22
samples/scanner/images/distroless-go/usage.cdx.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "distroless-go",
|
||||
"version": "2025.10.0",
|
||||
"bomRef": "pkg:docker/gcr.io/distroless/base@sha256:0dd2f0f15c9f8abfba6a0ce0d7d6a24e2e1071c977733f6e77cbe51b87f15ad9"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:golang/github.com/stellaops/sample-service@v1.4.0",
|
||||
"name": "github.com/stellaops/sample-service",
|
||||
"version": "v1.4.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
samples/scanner/images/dotnet-aot/README.md
Normal file
3
samples/scanner/images/dotnet-aot/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# .NET AOT Sample
|
||||
|
||||
An ahead-of-time compiled worker showcasing how native .NET deployments appear in SBOM outputs. The BOM Index ties NuGet packages back to the generated `deps.json` evidence.
|
||||
52
samples/scanner/images/dotnet-aot/bom-index.json
Normal file
52
samples/scanner/images/dotnet-aot/bom-index.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "registry.stella-ops.org/sample/dotnet-aot",
|
||||
"digest": "sha256:5be6f3ad9d2b1e4fcb4c6f40d9c664fca97f5b4d9ccb8e1d8f970e8b2bce1123",
|
||||
"tag": "1.0.0"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:nuget/Sample.Worker@1.0.0",
|
||||
"layerDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "deps-json",
|
||||
"path": "/app/Sample.Worker.deps.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:nuget/Microsoft.Extensions.Hosting@8.0.0",
|
||||
"layerDigest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "deps-json",
|
||||
"path": "/app/Sample.Worker.deps.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:nuget/System.Text.Json@8.0.0",
|
||||
"layerDigest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "deps-json",
|
||||
"path": "/app/Sample.Worker.deps.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:nuget/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross@8.0.0",
|
||||
"layerDigest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "deps-json",
|
||||
"path": "/app/Sample.Worker.deps.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
40
samples/scanner/images/dotnet-aot/inventory.cdx.json
Normal file
40
samples/scanner/images/dotnet-aot/inventory.cdx.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "dotnet-aot",
|
||||
"version": "8.0.0",
|
||||
"bomRef": "pkg:docker/stellaops/sample-dotnet-aot@sha256:5be6f3ad9d2b1e4fcb4c6f40d9c664fca97f5b4d9ccb8e1d8f970e8b2bce1123"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:nuget/Sample.Worker@1.0.0",
|
||||
"name": "Sample.Worker",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:nuget/Microsoft.Extensions.Hosting@8.0.0",
|
||||
"name": "Microsoft.Extensions.Hosting",
|
||||
"version": "8.0.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:nuget/System.Text.Json@8.0.0",
|
||||
"name": "System.Text.Json",
|
||||
"version": "8.0.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:nuget/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross@8.0.0",
|
||||
"name": "NativeAotRuntime",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
samples/scanner/images/dotnet-aot/usage.cdx.json
Normal file
28
samples/scanner/images/dotnet-aot/usage.cdx.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "dotnet-aot",
|
||||
"version": "8.0.0",
|
||||
"bomRef": "pkg:docker/stellaops/sample-dotnet-aot@sha256:5be6f3ad9d2b1e4fcb4c6f40d9c664fca97f5b4d9ccb8e1d8f970e8b2bce1123"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:nuget/Sample.Worker@1.0.0",
|
||||
"name": "Sample.Worker",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:nuget/System.Text.Json@8.0.0",
|
||||
"name": "System.Text.Json",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
samples/scanner/images/nginx/README.md
Normal file
3
samples/scanner/images/nginx/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Nginx Inventory Sample
|
||||
|
||||
CycloneDX inventory, usage, and BOM Index fixtures for the `docker.io/library/nginx:1.25.4` image. The SBOMs capture base Alpine packages and the BOM Index links each component to the layer that introduced it.
|
||||
52
samples/scanner/images/nginx/bom-index.json
Normal file
52
samples/scanner/images/nginx/bom-index.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "docker.io/library/nginx",
|
||||
"digest": "sha256:8f47d7c6b538c0d9533b78913cba3d5e671e7c4b4e7c6a2bb9a1a1c4d4f8e123",
|
||||
"tag": "1.25.4"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:apk/alpine/nginx@1.25.4-r1?arch=x86_64",
|
||||
"layerDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["BSD-2-Clause"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:apk/alpine/openssl@3.2.2-r0?arch=x86_64",
|
||||
"layerDigest": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["Apache-2.0"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:apk/alpine/pcre2@10.42-r1?arch=x86_64",
|
||||
"layerDigest": "sha256:3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["BSD-3-Clause"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:apk/alpine/zlib@1.3-r2?arch=x86_64",
|
||||
"layerDigest": "sha256:4444444444444444444444444444444444444444444444444444444444444444",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["Zlib"],
|
||||
"evidence": {
|
||||
"kind": "apk-database",
|
||||
"path": "/lib/apk/db/installed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
53
samples/scanner/images/nginx/inventory.cdx.json
Normal file
53
samples/scanner/images/nginx/inventory.cdx.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "nginx",
|
||||
"version": "1.25.4",
|
||||
"bomRef": "pkg:docker/library/nginx@sha256:8f47d7c6b538c0d9533b78913cba3d5e671e7c4b4e7c6a2bb9a1a1c4d4f8e123"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"name": "StellaOps Scanner",
|
||||
"version": "10.0.0-preview1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:apk/alpine/nginx@1.25.4-r1?arch=x86_64",
|
||||
"name": "nginx",
|
||||
"version": "1.25.4-r1",
|
||||
"licenses": [
|
||||
{
|
||||
"license": {
|
||||
"id": "2BSD"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/openssl@3.2.2-r0?arch=x86_64",
|
||||
"name": "openssl",
|
||||
"version": "3.2.2-r0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/pcre2@10.42-r1?arch=x86_64",
|
||||
"name": "pcre2",
|
||||
"version": "10.42-r1"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/zlib@1.3-r2?arch=x86_64",
|
||||
"name": "zlib",
|
||||
"version": "1.3-r2"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
samples/scanner/images/nginx/usage.cdx.json
Normal file
28
samples/scanner/images/nginx/usage.cdx.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "nginx",
|
||||
"version": "1.25.4",
|
||||
"bomRef": "pkg:docker/library/nginx@sha256:8f47d7c6b538c0d9533b78913cba3d5e671e7c4b4e7c6a2bb9a1a1c4d4f8e123"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:apk/alpine/nginx@1.25.4-r1?arch=x86_64",
|
||||
"name": "nginx",
|
||||
"version": "1.25.4-r1"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:apk/alpine/openssl@3.2.2-r0?arch=x86_64",
|
||||
"name": "openssl",
|
||||
"version": "3.2.2-r0"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
samples/scanner/images/npm-monorepo/README.md
Normal file
3
samples/scanner/images/npm-monorepo/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# NPM Monorepo Sample
|
||||
|
||||
Mirrors the fixture under `samples/runtime/npm-monorepo`. The SBOMs highlight the workspace packages plus transitive dependencies, and the BOM Index pins evidence to individual `package.json` files.
|
||||
52
samples/scanner/images/npm-monorepo/bom-index.json
Normal file
52
samples/scanner/images/npm-monorepo/bom-index.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "registry.stella-ops.org/samples/npm-monorepo",
|
||||
"digest": "sha256:1cf2ab9d373086ed5bd1a8f4aa6f491f8844bbb0d6be8df449c16ad6c8fa7c55",
|
||||
"tag": "2025.10.0"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:npm/%40stella/web@1.5.3",
|
||||
"layerDigest": "sha256:1212121212121212121212121212121212121212121212121212121212121212",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "package-json",
|
||||
"path": "node_modules/@stella/web/package.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:npm/%40stella/core@2.0.0",
|
||||
"layerDigest": "sha256:1313131313131313131313131313131313131313131313131313131313131313",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["Apache-2.0"],
|
||||
"evidence": {
|
||||
"kind": "package-json",
|
||||
"path": "node_modules/@stella/core/package.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:npm/lodash@4.17.21",
|
||||
"layerDigest": "sha256:1414141414141414141414141414141414141414141414141414141414141414",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "package-json",
|
||||
"path": "node_modules/lodash/package.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:npm/rxjs@7.8.1",
|
||||
"layerDigest": "sha256:1515151515151515151515151515151515151515151515151515151515151515",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["Apache-2.0"],
|
||||
"evidence": {
|
||||
"kind": "package-json",
|
||||
"path": "node_modules/rxjs/package.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
40
samples/scanner/images/npm-monorepo/inventory.cdx.json
Normal file
40
samples/scanner/images/npm-monorepo/inventory.cdx.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "npm-monorepo",
|
||||
"version": "2025.10.0",
|
||||
"bomRef": "pkg:docker/registry.stella-ops.org/samples/npm-monorepo@sha256:1cf2ab9d373086ed5bd1a8f4aa6f491f8844bbb0d6be8df449c16ad6c8fa7c55"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:npm/%40stella/core@2.0.0",
|
||||
"name": "@stella/core",
|
||||
"version": "2.0.0"
|
||||
},
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:npm/%40stella/web@1.5.3",
|
||||
"name": "@stella/web",
|
||||
"version": "1.5.3"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:npm/lodash@4.17.21",
|
||||
"name": "lodash",
|
||||
"version": "4.17.21"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:npm/rxjs@7.8.1",
|
||||
"name": "rxjs",
|
||||
"version": "7.8.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
34
samples/scanner/images/npm-monorepo/usage.cdx.json
Normal file
34
samples/scanner/images/npm-monorepo/usage.cdx.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "npm-monorepo",
|
||||
"version": "2025.10.0",
|
||||
"bomRef": "pkg:docker/registry.stella-ops.org/samples/npm-monorepo@sha256:1cf2ab9d373086ed5bd1a8f4aa6f491f8844bbb0d6be8df449c16ad6c8fa7c55"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:npm/%40stella/web@1.5.3",
|
||||
"name": "@stella/web",
|
||||
"version": "1.5.3"
|
||||
},
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:npm/%40stella/core@2.0.0",
|
||||
"name": "@stella/core",
|
||||
"version": "2.0.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:npm/rxjs@7.8.1",
|
||||
"name": "rxjs",
|
||||
"version": "7.8.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
samples/scanner/images/python-venv/README.md
Normal file
3
samples/scanner/images/python-venv/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Python Virtualenv Sample
|
||||
|
||||
Pairs with the runtime fixture under `samples/runtime/python-venv`. The SBOMs highlight how requests pulls in urllib3 and certifi, and the BOM Index records the `*.dist-info/METADATA` evidence paths used by the Python analyzer.
|
||||
42
samples/scanner/images/python-venv/bom-index.json
Normal file
42
samples/scanner/images/python-venv/bom-index.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"schema": "stellaops/bom-index@1",
|
||||
"image": {
|
||||
"repository": "docker.io/library/python",
|
||||
"digest": "sha256:dbed08b7d9675c2be627bbecac182a04c36d3f4ffd542c4fba7c7a850a6578dc",
|
||||
"tag": "3.12-slim"
|
||||
},
|
||||
"generatedAt": "2025-10-19T00:00:00Z",
|
||||
"generator": "stellaops/scanner@10.0.0-preview1",
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:pypi/requests@2.32.0",
|
||||
"layerDigest": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["Apache-2.0"],
|
||||
"evidence": {
|
||||
"kind": "dist-info",
|
||||
"path": "lib/python3.11/site-packages/requests-2.32.0.dist-info/METADATA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:pypi/urllib3@2.2.1",
|
||||
"layerDigest": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"usage": ["inventory", "runtime"],
|
||||
"licenses": ["MIT"],
|
||||
"evidence": {
|
||||
"kind": "dist-info",
|
||||
"path": "lib/python3.11/site-packages/urllib3-2.2.1.dist-info/METADATA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"purl": "pkg:pypi/certifi@2024.6.2",
|
||||
"layerDigest": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"usage": ["inventory"],
|
||||
"licenses": ["MPL-2.0"],
|
||||
"evidence": {
|
||||
"kind": "dist-info",
|
||||
"path": "lib/python3.11/site-packages/certifi-2024.6.2.dist-info/METADATA"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
34
samples/scanner/images/python-venv/inventory.cdx.json
Normal file
34
samples/scanner/images/python-venv/inventory.cdx.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "python-venv",
|
||||
"version": "3.12-slim",
|
||||
"bomRef": "pkg:docker/library/python@sha256:dbed08b7d9675c2be627bbecac182a04c36d3f4ffd542c4fba7c7a850a6578dc"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:pypi/requests@2.32.0",
|
||||
"name": "requests",
|
||||
"version": "2.32.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:pypi/urllib3@2.2.1",
|
||||
"name": "urllib3",
|
||||
"version": "2.2.1"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:pypi/certifi@2024.6.2",
|
||||
"name": "certifi",
|
||||
"version": "2024.6.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
samples/scanner/images/python-venv/usage.cdx.json
Normal file
28
samples/scanner/images/python-venv/usage.cdx.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"timestamp": "2025-10-19T00:00:00Z",
|
||||
"component": {
|
||||
"type": "container",
|
||||
"name": "python-venv",
|
||||
"version": "3.12-slim",
|
||||
"bomRef": "pkg:docker/library/python@sha256:dbed08b7d9675c2be627bbecac182a04c36d3f4ffd542c4fba7c7a850a6578dc"
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "application",
|
||||
"bomRef": "pkg:pypi/requests@2.32.0",
|
||||
"name": "requests",
|
||||
"version": "2.32.0"
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bomRef": "pkg:pypi/urllib3@2.2.1",
|
||||
"name": "urllib3",
|
||||
"version": "2.2.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user