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.jsonArt. 13(23)
2SBOM Signing (Cosign).sig + .certArt. 10(12)
3SBOM AttestationGitHub AttestationArt. 10(12)
4Vulnerability Scanvulnerability-report.jsonArt. 10(6)
5VEX Generationvex.openvex.jsonAnnex I II.2
6Compliance Report.json + .mdAnnex VII
7SARIF UploadGitHub Security tabArt. 10(8)
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 (Art. 10 Abs. 8). 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 MaterialsArt. 13(23)
sbom.cdx.json.sigCosign SignatureSBOM integrity (portable)Art. 10(12)
sbom.cdx.json.certX.509 CertificateSigning identityArt. 10(12)
GitHub AttestationSigstoreSBOM provenance (GitHub-native)Art. 10(12)
vulnerability-report.jsonTrivy JSONKnown vulnerabilitiesArt. 10(6)
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