This document is under active development and has not been finalised.
Skip to content

8.2 Automation Workflows

Architecture

BAUER GROUP's CRA automation is split across two repositories:

  • CRA-specific workflows and actions live in SEC-CRACompliance (this repo)
  • Generic actions (VEX generation, SBOM attestation) live in automation-templates

Consumer repositories (your products) call the CRA release workflow with a single uses: line.

┌──────────────────────────────────────────┐
│            Consumer Repo (Product)        │
│                                          │
│  uses: bauer-group/SEC-CRACompliance/    │
│        .github/workflows/cra-release.yml │
└──────────────────┬───────────────────────┘

    ┌──────────────┼──────────────┐
    ▼              ▼              ▼
┌─────────┐  ┌──────────┐  ┌────────────┐
│ CRA-Repo│  │ CRA-Repo │  │ Automation │
│ Actions │  │ Actions  │  │ Templates  │
├─────────┤  ├──────────┤  ├────────────┤
│ SBOM    │  │Compliance│  │ VEX        │
│ Sign    │  │ Report   │  │ Attestation│
│ Scan    │  │          │  │            │
│ Hub     │  │          │  │            │
└─────────┘  └──────────┘  └────────────┘
CRA-specific  CRA-specific    Generic

Reusable Workflows

cra-release.yml — Release Artifacts

The primary workflow. Generates, signs, and archives all CRA artifacts for a release.

Usage (zero-config):

yaml
jobs:
  cra:
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-release.yml@main
    permissions:
      contents: write
      id-token: write
      attestations: write
      security-events: write

Usage (customised):

yaml
jobs:
  cra:
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-release.yml@main
    with:
      run-validation: true
      validation-command: 'npm run ci'
      sign-sbom: true
      attest-sbom: true
      generate-vex: true
      generate-compliance-report: true
      support-period-years: 5
      fail-on-critical: true
    permissions:
      contents: write
      id-token: write
      attestations: write
      security-events: write

Pipeline flow:

StepActionArtifactCRA Reference
1SBOM Generationsbom.cdx.jsonAnnex I Part II (1)
2SBOM Signing (Cosign).sig + .certAnnex I Part II (7)
3SBOM AttestationGitHub AttestationAnnex I Part II (7)
4Vulnerability Scanvulnerability-report.jsonAnnex I Part II (1)
5VEX Generationvex.openvex.jsonAnnex I II.2
6Compliance Report.json + .mdAnnex VII
7SARIF UploadGitHub Security tabAnnex I Part I (2)(a)
8Release AttachmentAll artifacts on releaseArt. 13

Zero Config

All new features (attestation, VEX, compliance report) are enabled by default. Existing consumers get them automatically without workflow changes.

cra-scan.yml — Scheduled Vulnerability Scan

For continuous CVE monitoring (Annex I Part I (2)(a)). Run daily via cron schedule.

yaml
on:
  schedule:
    - cron: '0 6 * * *'

jobs:
  scan:
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-scan.yml@main
    with:
      severity-threshold: MEDIUM
      fail-on-critical: false
      create-issue: true
    permissions:
      contents: read
      security-events: write
      issues: write

Features:

  • Multi-engine scanning (Trivy + Grype + OSV-Scanner)
  • Automatic GitHub Issue creation for CRITICAL findings
  • SARIF upload to GitHub Security tab
  • Configurable severity thresholds

cra-report.yml — Hub API Report

Sends compliance data to the Software Security Hub API for centralised tracking.

yaml
jobs:
  report:
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-report.yml@main
    with:
      send-sbom: true
      send-vulnerabilities: true
      send-release-info: true

Complete Consumer Workflow

COPY & PASTE

Copy this workflow into your product repository as .github/workflows/cra.yml. It covers release compliance, weekly scanning, and Hub reporting — all with sensible defaults.

Minimal (Zero-Config)

Works out of the box for any repository. All features enabled with defaults.

yaml
# .github/workflows/cra.yml
name: CRA Compliance

on:
  release:
    types: [published]
  schedule:
    - cron: '0 6 * * 1'  # Weekly Monday 06:00 UTC
  workflow_dispatch:

permissions:
  contents: write
  id-token: write
  attestations: write
  security-events: write
  issues: write

jobs:
  # On release: Full CRA pipeline
  cra-release:
    if: github.event_name == 'release'
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-release.yml@main
    permissions:
      contents: write
      id-token: write
      attestations: write
      security-events: write

  # Weekly: CVE scan
  cra-scan:
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-scan.yml@main
    permissions:
      contents: read
      security-events: write
      issues: write

Full Configuration (all parameters)

For products with specific requirements — Node.js validation, Class I classification, Grype scanning, etc.

yaml
# .github/workflows/cra.yml
name: CRA Compliance

on:
  release:
    types: [published]
  schedule:
    - cron: '0 6 * * 1'
  workflow_dispatch:

permissions:
  contents: write
  id-token: write
  attestations: write
  security-events: write
  issues: write

jobs:
  # ── Release: Full CRA pipeline ──
  cra-release:
    if: github.event_name == 'release'
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-release.yml@main
    with:
      # Validation
      run-validation: true              # Run lint/build before CRA artifacts
      node-version: '24'                # Node.js version for validation
      validation-command: 'npm run ci'  # Your validation command

      # SBOM & Scanning
      scan-target: '.'                  # Directory, image ref, or SBOM path
      scan-type: 'auto'                 # auto | fs | image | sbom
      sign-sbom: true                   # Cosign keyless signing
      fail-on-critical: true            # Block release on CRITICAL CVEs
      enable-grype: true                # Additional Grype scan
      enable-osv: true                  # Additional OSV-Scanner

      # Attestation & VEX
      attest-sbom: true                 # GitHub-native SBOM attestation
      generate-vex: true                # OpenVEX document
      vex-overrides: 'security/vex-overrides.json'  # Manual triage file

      # Compliance Report
      generate-compliance-report: true
      support-period-years: 5           # Art. 13(8): minimum 5 years

      # EU Declaration of Conformity
      generate-eu-doc: true             # Annex V JSON
      render-pdfs: true                 # JSON → PDF rendering
      classification: 'important-class-1'  # standard | important-class-1 | important-class-2 | critical
      conformity-module: 'module-a'     # module-a | module-b-c | module-h | eucc
      manufacturer-name: 'BAUER GROUP GmbH'

      # Release
      upload-to-release: true           # Attach all artifacts to GitHub Release
      retention-days: 90                # Artifact retention
    permissions:
      contents: write
      id-token: write
      attestations: write
      security-events: write

  # ── Weekly: CVE Scan ──
  cra-scan:
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-scan.yml@main
    with:
      severity-threshold: 'MEDIUM'      # UNKNOWN | LOW | MEDIUM | HIGH | CRITICAL
      fail-on-critical: false           # Don't fail scheduled scans
      create-issue: true                # Create GitHub Issue for CRITICAL CVEs
      enable-grype: true
      enable-osv: true
    permissions:
      contents: read
      security-events: write
      issues: write

  # ── After Release: Report to Hub ──
  cra-report:
    if: github.event_name == 'release'
    needs: [cra-release]
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-report.yml@main
    with:
      dry-run: true                     # Set false when Hub is operational
    permissions:
      contents: read
      id-token: write

Docker / Container Image

For products that build container images — scan the image instead of the filesystem.

yaml
jobs:
  cra-release:
    if: github.event_name == 'release'
    uses: bauer-group/SEC-CRACompliance/.github/workflows/cra-release.yml@main
    with:
      scan-target: 'ghcr.io/bauer-group/my-app:${{ github.ref_name }}'
      scan-type: 'image'
      classification: 'important-class-2'
    permissions:
      contents: write
      id-token: write
      attestations: write
      security-events: write

Instead of passing all parameters in the workflow, create a cra-product.json in your repository root. The cra-eu-doc action reads it automatically:

json
{
  "$schema": "https://cra.docs.bauer-group.com/schemas/cra-product/v1.0.0",
  "product": {
    "name": "API-Gateway",
    "description": "REST API Gateway for BAUER GROUP services",
    "classification": "important-class-1",
    "conformityModule": "module-a"
  },
  "manufacturer": {
    "name": "BAUER GROUP GmbH",
    "address": "Street, City, Country"
  },
  "support": {
    "periodYears": 5,
    "until": "2031-12-31"
  },
  "contacts": {
    "securityEmail": "disclosure@bauer-group.com",
    "productOwner": "team@bauer-group.com"
  }
}

Parameter Reference

cra-release.yml

ParameterTypeDefaultDescription
run-validationbooleanfalseRun lint/build before CRA artifacts
node-versionstring'24'Node.js version (if run-validation: true)
validation-commandstring'npm run lint'Validation command
scan-targetstring'.'Directory, image ref, or SBOM file path
scan-typestring'auto'auto, fs, image, or sbom
sbom-filenamestring'sbom.cdx.json'SBOM output filename
sign-sbombooleantrueSign SBOM with Cosign (keyless)
fail-on-criticalbooleanfalseFail if CRITICAL vulnerabilities found
enable-grypebooleanfalseRun Grype as additional scanner
enable-osvbooleantrueRun OSV-Scanner
attest-sbombooleantrueCreate GitHub SBOM attestation
generate-vexbooleantrueGenerate OpenVEX document
vex-overridesstring'security/vex-overrides.json'Path to VEX triage overrides
generate-compliance-reportbooleantrueGenerate JSON + Markdown report
support-period-yearsnumber5Support period (Art. 13(8))
generate-eu-docbooleantrueGenerate EU Declaration of Conformity
render-pdfsbooleantrueRender JSON → PDF
classificationstring'standard'CRA class: standard, important-class-1, important-class-2, critical
conformity-modulestring'module-a'Module: module-a, module-b-c, module-h, eucc
manufacturer-namestring'BAUER GROUP GmbH'Manufacturer legal name
upload-to-releasebooleantrueAttach artifacts to GitHub Release
retention-daysnumber90Artifact retention in days

cra-scan.yml

ParameterTypeDefaultDescription
scan-targetstring'.'Scan target
scan-typestring'auto'Scan type
severity-thresholdstring'MEDIUM'Minimum severity to report
fail-on-criticalbooleanfalseFail on CRITICAL findings
create-issuebooleantrueCreate GitHub Issue for CRITICALs
enable-grypebooleanfalseAdditional Grype scan
enable-osvbooleantrueAdditional OSV-Scanner

Required Permissions

WorkflowPermissionWhy
cra-releasecontents: writeUpload release assets
cra-releaseid-token: writeCosign keyless signing (OIDC)
cra-releaseattestations: writeGitHub SBOM attestation
cra-releasesecurity-events: writeSARIF upload to Security tab
cra-scancontents: readRead repository for scanning
cra-scansecurity-events: writeSARIF upload
cra-scanissues: writeCreate CVE issues
cra-reportcontents: readRead SBOM + scan results
cra-reportid-token: writeAPI authentication

Release Artifacts

A fully configured CRA release produces:

ArtifactFormatPurposeCRA Reference
sbom.cdx.jsonCycloneDX JSONSoftware Bill of MaterialsAnnex I Part II (1)
sbom.cdx.json.sigCosign SignatureSBOM integrity (portable)Annex I Part II (7)
sbom.cdx.json.certX.509 CertificateSigning identityAnnex I Part II (7)
GitHub AttestationSigstoreSBOM provenance (GitHub-native)Annex I Part II (7)
vulnerability-report.jsonTrivy JSONKnown vulnerabilitiesAnnex I Part II (1)
vex.openvex.jsonOpenVEX v0.2.0Vulnerability exploitabilityAnnex I II.2
cra-compliance-report.jsonCustom Schema v1.0.0Machine-readable compliance statusAnnex VII
cra-compliance-report.mdMarkdownHuman-readable compliance statusAnnex VII
eu-doc.jsonEU DoC Schema v1.0.0Machine-readable EU Declaration of ConformityArt. 28, Annex V
EU-Declaration-*.pdfPDFPrintable EU Declaration of ConformityArt. 28, Annex V
CRA-Compliance-Report-*.pdfPDFPrintable compliance reportAnnex VII

VERIFICATION

Verify SBOM authenticity after download:

bash
# Cosign
cosign verify-blob --signature sbom.cdx.json.sig --certificate sbom.cdx.json.cert sbom.cdx.json

# GitHub Attestation
gh attestation verify sbom.cdx.json --repo owner/repo

VEX Triage

The VEX document auto-generates under_investigation statements for all found CVEs. To triage:

  1. Create security/vex-overrides.json in your product repo
  2. Add manual decisions for each CVE
json
{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "statements": [
    {
      "vulnerability": { "@id": "CVE-2024-1234" },
      "products": [{ "@id": "pkg:github/your-org/your-repo" }],
      "status": "not_affected",
      "justification": "vulnerable_code_not_in_execute_path",
      "impact_statement": "Dependency imported but affected function never called."
    }
  ]
}
StatusWhen to use
not_affectedVulnerability exists but is not exploitable in your product
affectedVulnerability is exploitable — remediation required
fixedVulnerability has been remediated
under_investigationAssessment pending (auto-generated default)

Compliance Scoring

The compliance report assigns a score out of 100:

CategoryMaxCriteria
SBOM20Generated (10) + Signed (5) + Attested (5)
Signing15Cosign verified (10) + Attestation present (5)
Vulnerabilities200 critical (15) + 0 high (5)
VEX10Generated (5) + Manual overrides present (5)
Security Policy15SECURITY.md (10) + CVD process defined (5)
Support Period10Defined in config (10)
CRA Article Coverage10Percentage of mapped articles met

CLI TOOL

Use the cra-check CLI to verify compliance locally or for any GitHub repo.

Documentation licensed under CC BY-NC 4.0 · Code licensed under MIT