Files
git.stella-ops.org/docs/modules/scanner/design/competitor-signature-verification.md
StellaOps Bot 8768c27f30
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals DSSE Sign & Evidence Locker / sign-signals-artifacts (push) Has been cancelled
Signals DSSE Sign & Evidence Locker / verify-signatures (push) Has been cancelled
Add signal contracts for reachability, exploitability, trust, and unknown symbols
- Introduced `ReachabilityState`, `RuntimeHit`, `ExploitabilitySignal`, `ReachabilitySignal`, `SignalEnvelope`, `SignalType`, `TrustSignal`, and `UnknownSymbolSignal` records to define various signal types and their properties.
- Implemented JSON serialization attributes for proper data interchange.
- Created project files for the new signal contracts library and corresponding test projects.
- Added deterministic test fixtures for micro-interaction testing.
- Included cryptographic keys for secure operations with cosign.
2025-12-05 00:27:00 +02:00

7.2 KiB

Competitor SBOM/Scan Signature Verification (CM2)

Status: Draft · Date: 2025-12-04 Scope: Specify signature and provenance verification requirements for accepting external SBOM and scan outputs, including rejection/flag policies.

Objectives

  • Define acceptable signature algorithms and formats.
  • Establish trust root management for external signers.
  • Specify verification workflow and failure modes.
  • Enable offline verification with bundled trust roots.

Acceptable Signatures

Signature Formats

Format Algorithm Key Type Status
DSSE Ed25519 Asymmetric Preferred
DSSE ECDSA P-256 Asymmetric Accepted
DSSE RSA-2048+ Asymmetric Accepted
COSE EdDSA Asymmetric Accepted
JWS ES256 Asymmetric Accepted
JWS RS256 Asymmetric Deprecated

Hash Algorithms

Algorithm Usage Status
SHA-256 Primary Required
BLAKE3-256 Secondary Preferred
SHA-384 Alternative Accepted
SHA-512 Alternative Accepted
SHA-1 Legacy Rejected
MD5 Legacy Rejected

Trust Root Management

Bundled Trust Roots

out/offline/competitor-ingest-kit-v1/trust/
├── root-ca.pem              # CA for signed SBOMs
├── keyring.json             # Known signing keys
├── cosign-keys/             # Cosign public keys
│   ├── syft-release.pub
│   ├── trivy-release.pub
│   └── clair-release.pub
└── fulcio-root.pem          # Sigstore Fulcio CA

Keyring Format

{
  "keys": [
    {
      "id": "syft-release-2025",
      "type": "ecdsa-p256",
      "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
      "issuer": "https://github.com/anchore/syft",
      "validFrom": "2025-01-01T00:00:00Z",
      "validTo": "2026-01-01T00:00:00Z",
      "purposes": ["sbom-signing", "attestation-signing"]
    }
  ],
  "trustedIssuers": [
    "https://github.com/anchore/syft",
    "https://github.com/aquasecurity/trivy",
    "https://github.com/quay/clair"
  ]
}

Verification Workflow

┌─────────────┐
│  Receive    │
│   SBOM      │
└─────────────┘
       │
       ▼
┌─────────────┐     ┌─────────────┐
│ Has DSSE?   │──No─► Has JWS?    │──No─► Unsigned
└─────────────┘     └─────────────┘          │
       │                   │                 │
      Yes                 Yes                │
       │                   │                 │
       ▼                   ▼                 ▼
┌─────────────┐     ┌─────────────┐  ┌─────────────┐
│ Verify DSSE │     │ Verify JWS  │  │ Apply CM6   │
│  Signature  │     │  Signature  │  │  Fallback   │
└─────────────┘     └─────────────┘  └─────────────┘
       │                   │                 │
       ▼                   ▼                 ▼
┌─────────────┐     ┌─────────────┐  ┌─────────────┐
│   Valid?    │     │   Valid?    │  │ Provenance: │
└─────────────┘     └─────────────┘  │   unknown   │
    │     │             │     │      └─────────────┘
   Yes    No           Yes    No
    │     │             │     │
    ▼     ▼             ▼     ▼
 Accept  Reject      Accept  Reject

Verification Steps

  1. Format Detection

    • Check for DSSE envelope wrapper
    • Check for detached signature file (.sig)
    • Check for inline JWS header
  2. Signature Extraction

    • Parse envelope/signature structure
    • Extract signer key ID and algorithm
  3. Key Lookup

    • Search bundled keyring for key ID
    • Verify key is within validity period
    • Check key purpose matches usage
  4. Cryptographic Verification

    • Verify signature over payload
    • Verify hash matches content
    • Check for signature expiry
  5. Provenance Validation

    • Extract signer identity
    • Verify issuer is trusted
    • Check build metadata if present

Failure Modes

Rejection Reasons

Code Reason Action
sig_missing No signature present Apply fallback (CM6)
sig_invalid Signature verification failed Reject
sig_expired Signature validity period exceeded Reject
key_unknown Signing key not in keyring Reject
key_expired Signing key validity exceeded Reject
key_revoked Signing key has been revoked Reject
issuer_untrusted Issuer not in trusted list Reject
alg_unsupported Algorithm not acceptable Reject
hash_mismatch Content hash doesn't match Reject

Flag Policy

When --allow-unsigned is set:

Condition Behavior
Signature missing Accept with provenance=unknown, emit warning
Signature invalid Reject (flag doesn't override invalid)
Key unknown Accept with provenance=unverified, emit warning

Verification API

Endpoint

POST /api/v1/ingest/verify
Content-Type: application/json

{
  "sbom": "<base64-encoded-sbom>",
  "signature": "<base64-encoded-signature>",
  "options": {
    "allowUnsigned": false,
    "requireProvenance": true
  }
}

Response

{
  "verification": {
    "status": "valid",
    "signature": {
      "format": "dsse",
      "algorithm": "ecdsa-p256",
      "keyId": "syft-release-2025",
      "signedAt": "2025-12-04T00:00:00Z"
    },
    "provenance": {
      "issuer": "https://github.com/anchore/syft",
      "buildId": "build-12345",
      "sourceRepo": "https://github.com/example/app"
    },
    "hash": {
      "algorithm": "sha256",
      "value": "..."
    }
  }
}

Offline Verification

Requirements

  • All trust roots bundled in offline kit
  • No network calls during verification
  • Keyring includes all expected signers
  • CRL/OCSP checks disabled (use bundled revocation lists)

Revocation List Format

{
  "revoked": [
    {
      "keyId": "compromised-key-2024",
      "revokedAt": "2024-12-01T00:00:00Z",
      "reason": "Key compromise"
    }
  ],
  "lastUpdated": "2025-12-04T00:00:00Z"
}

Integration with Normalization (CM1)

After successful verification:

  1. Extract tool metadata from signature/provenance
  2. Pass to normalization adapter
  3. Include verification result in normalized output
{
  "source": {
    "tool": "syft",
    "version": "1.0.0",
    "hash": "sha256:..."
  },
  "verification": {
    "status": "verified",
    "keyId": "syft-release-2025",
    "signedAt": "2025-12-04T00:00:00Z"
  },
  "components": [...],
  "normalized_hash": "blake3:..."
}
  • Sprint: docs/implplan/SPRINT_0186_0001_0001_record_deterministic_execution.md (CM2)
  • Normalization: docs/modules/scanner/design/competitor-ingest-normalization.md (CM1)
  • Fallback: See CM6 in this document series