Files
git.stella-ops.org/docs/modules/policy/cvss-v4.md
StellaOps Bot 68bc53a07b
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
up
2025-12-07 23:07:09 +02:00

7.2 KiB
Raw Blame History

CVSS v4.0 Receipts Hardening Guide

Source advisory: docs/product-advisories/25-Nov-2025 - Add CVSSv4.0 Score Receipts for Transparency.md (CV1CV10). This guide turns the gaps into implementable rules for Sprint 0190.

Canonical hashing (CV2)

  • Serializer: JSON Canonicalization Scheme (JCS).
  • Ordering: lexicographic keys; arrays keep order; drop nulls.
  • Numbers: fixed 4-decimal precision; invariant culture; no exponent.
  • Time: UTC ISO-8601 Z; strip milliseconds unless non-zero.
  • Hash: SHA-256 of canonical JSON; store as inputsHash and DSSE subject.
  • Test vectors: tests/Policy/StellaOps.Policy.Scoring.Tests/Fixtures/hashing/ (receipt-input.json + receipt-input.sha256).
  • Recompute locally:
    python - <<'PY'
    import json, hashlib, pathlib
    data=json.loads(pathlib.Path('tests/Policy/StellaOps.Policy.Scoring.Tests/Fixtures/hashing/receipt-input.json').read_text())
    canon=json.dumps(data, sort_keys=True, separators=(',', ':'), ensure_ascii=False)
    print(hashlib.sha256(canon.encode()).hexdigest())
    PY
    

Policy replay & backfill (CV1)

  • Policies immutable; bump version for any change.
  • On change, emit new receipts with supersedesReceiptId and retain old ones.
  • Backfill job: re-score under new policy, append history, re-sign DSSE.

Tenant segregation & RBAC (CV4, CV9)

  • Storage keys include tenantId; hashes/DSSE annotate tenant.
  • Roles: Security Engineer (Base), SOC Analyst (Threat), Customer Admin (Env), Viewer (read-only).
  • Enforce at API/repo layer and in canonical hash.

Deterministic exports (CV8)

  • JSON export: JCS ordering, UTF-8, UTC timestamps, stable severity palette.
  • PDF export: embed fonts (Source Sans 3 + Roboto Mono), A4, fixed margins; hash PDF bytes and persist exportHash.
  • Offline receipt bundle: include JSON, PDF, DSSE envelope, and policy hash; tar with sorted names + fixed mtime.

v3.1 → v4.0 conversion (CV5)

  • Deterministic mapping; tag source: "converted-v3.1", set conversionMethod + confidence; retain vendor vector.
  • Record conversionHash of the original v3.1 vector (JCS + SHA-256) and store in receipt history for audit.

Evidence provenance (CV6)

  • Evidence items use CAS URIs + DSSE refs, include retentionClass, redactionStatus, verifiedAt, hashMismatch.
  • Receipt schema enforces evidence array; DSSE subject hash must match inputsHash.

Immutability & monitoring (CV7, CV10)

  • Receipts append-only; amendments create new IDs + DSSE.
  • Alerts: DSSE verify failures, policy hash drift, hash mismatch, engine version skew. Prometheus counters: cvss_receipt_dsse_failures_total, cvss_policy_drift_total, cvss_hash_mismatch_total.
  • Receipt history includes supersedesReceiptId and amendsReceiptId; policy backfill job must set supersedesReceiptId when replaying.
  • Dashboard SLO: DSSE failure rate <0.1% per 24h; policy drift alerts page security on-call.

Golden fixtures & locations

  • Hashing vectors: tests/Policy/StellaOps.Policy.Scoring.Tests/Fixtures/hashing/receipt-input.json with expected hash receipt-input.sha256.
  • Receipt DSSE/PDF examples to live under tests/Policy/StellaOps.Policy.Scoring.Tests/Fixtures/receipts/ as exports land.
  • Sample PDFs in Fixtures/exports/ once generated; hash each to *.pdf.sha256.

Implementation checklist

  • Wire ReceiptCanonicalizer to JCS rules above.
  • Add backfill job + history persistence.
  • Enforce tenant/RBAC and annotate hashes/DSSE.
  • Implement deterministic PDF export and record exportHash.
  • Store conversion metadata for v3.1 sources.
  • Verify evidence CAS/DSSE on ingest; fail closed.
  • Expose metrics/alerts listed above.

Receipt model (API shape)

  • receiptId, schemaVersion, format, vulnerabilityId, tenantId, createdAt/by, modifiedAt/by.
  • Metric inputs: baseMetrics, optional threatMetrics and environmentalMetrics, optional supplementalMetrics.
  • Computed outputs: scores (base/threat/environmental/full plus effectiveScore and effectiveScoreType), vectorString, severity.
  • Policy link: policyRef { policyId, version, hash, activatedAt } plus inputHash (JCS + SHA-256) and optional exportHash.
  • Evidence: evidence[] (type, uri, description, source, collectedAt, dsseRef, isAuthoritative, isRedacted, verifiedAt, retentionClass).
  • Attestation + history: attestationRefs[] (DSSE envelopes), history[] (field, previousValue, newValue, actor, reason, referenceUri, when), amendsReceiptId, supersedesReceiptId, isActive.

Gateway API (Policy Engine via Gateway)

  • Base path: /api/cvss (Policy Gateway). Scopes: policy.run for create/amend; findings.read for read/history/policies.
  • Endpoints:
    • POST /api/cvss/receipts Create a receipt and optional DSSE envelope.
    • GET /api/cvss/receipts/{id} Fetch the latest receipt with scores, evidence, and hashes.
    • PUT /api/cvss/receipts/{id}/amend Append a history entry (e.g., policy change, evidence fix); re-sign when signingKey is provided.
    • GET /api/cvss/receipts/{id}/history Return ordered history entries for the receipt.
    • GET /api/cvss/policies List available CvssPolicy documents (id/version/hash/effective window).

Create receipt (minimal example)

POST /api/cvss/receipts
Authorization: Bearer <token>
Content-Type: application/json

{
  "vulnerabilityId": "CVE-2025-1234",
  "policy": {
    "policyId": "default",
    "version": "1.0.0",
    "name": "Default CVSS policy",
    "effectiveFrom": "2025-12-01T00:00:00Z",
    "hash": "sha256:..."
  },
  "baseMetrics": { "av": "Network", "ac": "Low", "at": "None", "pr": "None", "ui": "None", "vc": "High", "vi": "High", "va": "High", "sc": "High", "si": "High", "sa": "High" },
  "environmentalMetrics": { "cr": "High", "ir": "High", "ar": "Medium" },
  "signingKey": { "keyId": "cvss-dev", "store": "local" },
  "createdBy": "cli"
}

Response 200 (abridged)

{
  "receiptId": "cvss-20251207-01",
  "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/CR:H/IR:H/AR:M",
  "scores": { "baseScore": 9.3, "threatScore": 9.3, "environmentalScore": 9.1, "fullScore": 9.1, "effectiveScore": 9.1, "effectiveScoreType": "Environmental" },
  "severity": "Critical",
  "policyRef": { "policyId": "default", "version": "1.0.0", "hash": "sha256:..." },
  "inputHash": "sha256:...",
  "attestationRefs": ["dsse:stella.ops/cvssReceipt@v1/sha256:..."],
  "evidence": [],
  "history": []
}

CLI and UI usage

  • CLI (stella cvss ... via src/Cli/StellaOps.Cli):
    • stella cvss score --vuln CVE-2025-1234 --policy-file cvss-policy.json --vector CVSS:4.0/AV:N/... [--json]
    • stella cvss show <receiptId> [--json]
    • stella cvss history <receiptId> [--json]
    • stella cvss export <receiptId> --format json --out cvss-receipt.json
    • Uses Policy Gateway /api/cvss/... endpoints, enforces tenant scoping via --tenant/profile, and reuses CvssV4Engine locally for vector parsing.
  • Console (src/Web/StellaOps.Web):
    • Route /cvss/receipts/:receiptId renders a receipt viewer with score badge, vector summary, and tabs for Base/Threat/Environmental/Evidence/Policy/History.
    • Export and "Recalculate with my env" flows reuse the same receipt payload; UI expects deterministic ordering and stable hashes.