Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const badgeVariants = cva(
'bg-[#26264a] text-[#c2b8ff] ring-1 ring-[#565280] text-sm h-5',
devguardWebBadge:
'bg-[#162c41] text-[#3aadff] ring-1 ring-[#1d4d73] text-sm h-5',
upcoming:
'bg-blue-400/10 text-blue-400 ring-1 ring-blue-400 text-sm h-6',
},
},
defaultVariants: {
Expand Down
8 changes: 4 additions & 4 deletions src/pages/concepts/compliance-frameworks/iso.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ sidebar_position: 1

</summary>

- Identification and documentation of vulnerabilities in your codebase through [static code analysis](../other/concepts/devsecops/sast.mdx) and [dynamic code analysis](../other/concepts/devsecops/dast.mdx).
- Identification and documentation of vulnerabilities in your codebase through [static code analysis](../devsecops/sast.mdx) and [dynamic code analysis](../devsecops/dast.mdx).
- Identification and documentation of software components and libraries in your codebase through SBOM (Software Bill of Materials) generation, listing all software components with their versions.
- Automatic generation and documentation of an SBOM (Software Bill of Materials) with versions for each new change in the codebase.
- Identification and documentation of vulnerabilities in the dependencies of your codebase through dependency scanning with [software composition analysis](../other/concepts/devsecops/software-composition-analysis.mdx) (SCA) and [container images](../other/concepts/devsecops/container-scanning.mdx).
- Identification and documentation of vulnerabilities in the dependencies of your codebase through dependency scanning with [software composition analysis](../devsecops/software-composition-analysis.mdx) (SCA) and [container images](../devsecops/container-scanning.mdx).
- Verification of available patches for the vulnerabilities in dependencies, along with guidance on how to apply them.
- Calculation and documentation of the risk of vulnerabilities in your codebase and dependencies through risk analysis.
- Prioritization of vulnerabilities in your codebase and dependencies, enabling you to address the most critical issues first.
Expand Down Expand Up @@ -79,10 +79,10 @@ sidebar_position: 1

</summary>

- Identification and documentation of secrets and credentials in your codebase through [secret scanning](../other/concepts/devsecops/secret-scanning.mdx).
- Identification and documentation of secrets and credentials in your codebase through [secret scanning](../devsecops/secret-scanning.mdx).
- Identification and documentation of software components and libraries in your codebase through SBOM (Software Bill of Materials) generation, listing all software components with their versions.
- Automatic generation and documentation of an SBOM with versions for each new change in the codebase.
- Identification and documentation of vulnerabilities in the dependencies of your codebase through dependency scanning with [software composition analysis](../other/concepts/devsecops/software-composition-analysis.mdx) (SCA) and [container images](../other/concepts/devsecops/container-scanning.mdx).
- Identification and documentation of vulnerabilities in the dependencies of your codebase through dependency scanning with [software composition analysis](../devsecops/software-composition-analysis.mdx) (SCA) and [container images](../devsecops/container-scanning.mdx).
- Calculation and documentation of the risk of vulnerabilities in your codebase and dependencies through risk analysis.
- Ensuring the integrity of the codebase and protection from unauthorized changes through in-toto.
- Prioritization of vulnerabilities in your codebase and dependencies, enabling you to address the most critical issues first.
Expand Down
3 changes: 3 additions & 0 deletions src/pages/feature-guides/_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ export default {
'ingesting-upstream-information': {
title: 'Ingesting Upstream Information',
},
'csaf-common-security-advisory-framework': {
title: 'CSAF (Common Security Advisory Framework)',
},
'discover-base-image-attestations': {
title: 'Discovering Base Image Attestations',
},
Expand Down
174 changes: 174 additions & 0 deletions src/pages/feature-guides/csaf-common-security-advisory-framework.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { Badge } from "src/components/ui/badge"

# CSAF in DevGuard

<div className="mt-6 -mb-1">
<a href="https://github.com/l3montree-dev/devguard/issues?q=is%3Aissue%20state%3Aopen%20CSAF" target="_blank" rel="noreferrer noopener">
<Badge variant="upcoming">Upcoming Feature 🎉</Badge>
</a>
</div>

## Enabling CSAF Reports

To start publishing CSAF reports for your assets, follow these steps:

1. Navigate to your **Repository Settings**
2. Go to the **Vulnerability Management** section
3. Enable **"Enable public access to vulnerability data"**

Once enabled, your organization will be registered as a CSAF provider and your vulnerability data will be available through standardized CSAF endpoints.

## Accessing CSAF Data

After enabling CSAF reports, your organization's vulnerability data becomes accessible through a hierarchical structure:

### Instance Lister

On the instance level all organizations providing CSAF reports are listed:
- Primary endpoint: `https://api.main.devguard.org/api/v1/.well-known/csaf-aggregator/aggregator.json`
- Alternative endpoint: `https://main.devguard.org/.well-known/csaf-aggregator/aggregator.json`

Your organization will be **listed publicly** as a provider in this list once you enable public access to vulnerability data.

### Provider Metadata

Each organization has a provider metadata file that lists all repositories (assets) with CSAF reports available:

```
https://api.main.devguard.org/api/v1/organizations/{org-name}/csaf/provider-metadata.json
```

This file contains a `distributions` array listing `directory_url` your repositories (assets) that have CSAF reports enabled.

### Asset Reports

Individual vulnerability reports for each asset are organized by year and TLP (Traffic Light Protocol) (DevGuard currently only supports TLP:WHITE) level:

```
https://api.main.devguard.org/api/v1/organizations/{org-name}/projects/{project-name}/assets/{asset-name}/csaf/white/{year}/
```

Each asset will have a separate CSAF report for every vulnerability that has been detected throughout its lifetime.

[Example Index](https://api.main.devguard.org/api/v1/organizations/l3montree-cybersecurity/projects/devguard/assets/devguard-web/csaf/white/)
of the DevGuard backend repository.

## Consuming CSAF Reports as Upstream Data

DevGuard allows you to consume CSAF reports from other organizations as upstream vulnerability data.
This is particularly useful for tracking vulnerabilities in your dependencies. And it enabled sharing assessment results
between different teams and organizations.

### Configuration

When creating or updating an artifact, you can configure CSAF as an upstream source by saving an
upstreams CSAF URL and PURL to one of your assets:

1. **Provider Metadata URL**: The organization's CSAF provider metadata endpoint
```
https://api.main.devguard.org/api/v1/organizations/{org-name}/csaf/provider-metadata.json
```

2. **Package URL (PURL)**: The identifier for the specific asset you want to track. You usally get that PURL from your upstream.
Examples how that PURL can look like:

- A npm package:
```
pkg:npm/next@15.4.7
```

- For OCI containers:
```
pkg:oci/devguard@v0.19.0?repository_url=ghcr.io/l3montree-dev/devguard&tag=v0.19.0
```

- For DevGuard repositories:
```
pkg:devguard/{org}/{repo}@{ref}
```

### Upstream Event Handling

Once configured, CSAF upstream sources are processed using the same event handling mechanism as other upstream information
sources. For more details, see the [Ingesting Upstream Information](/feature-guides/ingesting-upstream-information) guide -
especially the section on [processing rules and behaviour](/feature-guides/ingesting-upstream-information#processing-rules-and-behavior).

## What is CSAF?

The **Common Security Advisory Framework (CSAF)** is an open standard for publishing security advisories in a structured, machine-readable format. Unlike traditional free-form text advisories, CSAF uses well-defined JSON documents to communicate vulnerability information consistently and precisely.

### Benefits of CSAF

- **Automated Processing**: Security information can be automatically consumed by vulnerability management tools and security dashboards
- **Reduced Manual Effort**: Eliminates the need to manually parse and interpret advisory information
- **Faster Response Times**: Organizations can respond more quickly and reliably to security risks
- **Standardized Format**: Consistent structure across different vendors and organizations

### CSAF in DevGuard

DevGuard leverages CSAF to provide comprehensive information about dependency vulnerabilities in your assets. Key features include:

- **Individual CVE Reports**: Each CVE affecting your asset gets its own dedicated CSAF report
- **Historical Tracking**: Complete history of each vulnerability throughout its lifetime
- **Rich Metadata**: Additional information including VEX states, affected packages, and detailed descriptions
- **Trusted Provider**: Organizations using DevGuard can become **CSAF trusted providers** once they've scanned their repositories

## What to Find in DevGuard's CSAF Reports?

Each CSAF report in DevGuard covers a single vulnerability affecting your asset. Reports follow the CSAF VEX (Vulnerability Exploitability eXchange) format and consist of two main components: the **Document** object and the **Vulnerabilities** object.

## A key difference between CSAF VEX & CyclonDX VEX

CSAF VEX has a product-centric view: You have a single product and communicate vulnerabilies of used
dependencies affecting that product without detailing the dependency graph. So the reciepient of the CSAF
report "just" sees product A is affected by vulnerability CVE-2025-1234, without details about which dependencies
of product A are affected.

```json filename="CSAF VEX Extract"
{
"vulnerabilities": [
{
"cve": "CVE-2024-53382",
"discovery_date": "2025-10-06T18:19:46Z",
"notes": [...],
"product_status": {
"under_investigation": [
"pkg:oci/devguard-web@main" // <- product PURL without details on affected dependency
]
},
"title": "CVE-2024-53382"
}
]
}
```

In contrast, CyclonDX VEX takes a component-centric approach, detailing vulnerabilities at the component level.
It provides the precise location of the affected dependency using the PURL of the affected package inside the product.

```json filename="CyclonDX VEX Extract"
{
...
"vulnerabilities": [
{
"id": "CVE-2024-53382",
"source": {
...
},
"ratings": [...],
"analysis": {
"state": "in_triage",
...
},
"affects": [
{
"ref": "pkg:npm/prismjs@1.27.0" // <- Detailed location PURL
}
]
}
]
}
```

Both are obviously correct in terms of content, but in case you get a SBOM next to the vulnerability reports, DevGuard has to try to match via the
CVE-ID instead of a direct mapping via PURL.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

DevGuard can automatically discover and extract attestations from container base images referenced in your Dockerfile. This enables you to ingest upstream vulnerability information from your container supply chain.

This feature is releated to the [Ingesting Upstream Information](../feature-guides/ingesting-upstream-information) guide, which explains how DevGuard processes VEX documents and SBOMs.
This feature is releated to the [Ingesting Upstream Information](../feature-guides/ingesting-upstream-information.mdx) guide, which explains how DevGuard processes VEX documents and SBOMs.

## Usage

Expand Down
4 changes: 2 additions & 2 deletions src/pages/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ calculation to follow soon. SBOM and VEX data are always up to date at these lin

|Project|SBOM|VeX|
|---|---|---|
|[Devguard Golang API](https://github.com/l3montree-dev/devguard)|[SBOM](https://main.devguard.org/l3montree-cybersecurity/projects/devguard/assets/devguard/sbom.json?scanType=container-scanning)|[VeX](https://main.devguard.org/l3montree-cybersecurity/projects/devguard/assets/devguard/vex.json?scanType=container-scanning)|
|[Devguard Web-Frontend](https://github.com/l3montree-dev/devguard-web)|[SBOM](https://main.devguard.org/l3montree-cybersecurity/projects/devguard/assets/devguard-web/sbom.json?scanType=container-scanning)|[VeX](https://main.devguard.org/l3montree-cybersecurity/projects/devguard/assets/devguard-web/vex.json?scanType=container-scanning)|
|[Devguard Golang API](https://github.com/l3montree-dev/devguard)|[SBOM](https://api.main.devguard.org/api/v1/public/e1f24270-6e68-4571-9168-9c151c639c97/sbom.json)|[VeX](https://api.main.devguard.org/api/v1/public/e1f24270-6e68-4571-9168-9c151c639c97/vex.json)|
|[Devguard Web-Frontend](https://github.com/l3montree-dev/devguard-web)|[SBOM](https://api.main.devguard.org/api/v1/public/169319b7-8170-469f-9e31-f87b6054e507/sbom.json)|[VeX](https://api.main.devguard.org/api/v1/public/169319b7-8170-469f-9e31-f87b6054e507/vex.json)|

## License

Expand Down
138 changes: 138 additions & 0 deletions utilities/verify-signature.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash
#
# GPG Signature Verification Script
# Verifies a detached signature against a document using an ASCII-armored public key
#
# Usage: verify-signature.sh <ascii-armored-keyfile> <signature-file> [document-file]
#
# Example: ./verify-signature.sh pubkey.asc cve-2025-54880.json.asc cve-2025-54880.json
#

set -euo pipefail

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Print usage information
usage() {
cat << EOF
Usage: $(basename "$0") <keyfile> <signature-file> [document-file]

Arguments:
keyfile ASCII-armored public key file (.asc)
signature-file Detached signature file (.asc or .sig)
document-file Document to verify (optional, auto-detected from signature filename)

Example:
$(basename "$0") pubkey.asc cve-2025-54880.json.asc cve-2025-54880.json
$(basename "$0") pubkey.asc document.sig document.txt

EOF
exit 1
}

# Check arguments
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
usage
fi

KEYFILE="$1"
SIGFILE="$2"

# Try to determine document file if not provided
if [ $# -eq 3 ]; then
DOCFILE="$3"
else
# Try to auto-detect by removing .asc or .sig extension
DOCFILE="${SIGFILE%.asc}"
DOCFILE="${DOCFILE%.sig}"

if [ "$DOCFILE" = "$SIGFILE" ]; then
echo -e "${RED}Error:${NC} Cannot auto-detect document file. Please specify it explicitly."
usage
fi

echo -e "${BLUE}Info:${NC} Auto-detected document file: $DOCFILE"
fi

# Validate input files
if [ ! -f "$KEYFILE" ]; then
echo -e "${RED}Error:${NC} Key file not found: $KEYFILE"
exit 1
fi

if [ ! -f "$SIGFILE" ]; then
echo -e "${RED}Error:${NC} Signature file not found: $SIGFILE"
exit 1
fi

if [ ! -f "$DOCFILE" ]; then
echo -e "${RED}Error:${NC} Document file not found: $DOCFILE"
exit 1
fi

# Create temporary keyring
TEMPKEY=$(mktemp -t verify-sig.XXXXXX).gpg

cleanup() {
rm -f "$TEMPKEY"
}
trap cleanup EXIT

# Convert ASCII-armored key to binary keyring
echo -e "${BLUE}Info:${NC} Converting public key to keyring..."
if ! gpg2 --yes -o "$TEMPKEY" --dearmor "$KEYFILE" 2>/dev/null; then
echo -e "${RED}Error:${NC} Failed to import public key"
exit 1
fi

# Verify signature
echo -e "${BLUE}Info:${NC} Verifying signature..."
echo

OUTPUT=$(gpg2 --status-fd 1 --no-default-keyring --keyring "$TEMPKEY" --trust-model always --verify "$SIGFILE" "$DOCFILE" 2>/dev/null)

echo "$OUTPUT"

# Check verification result
if echo "$OUTPUT" | grep -q "GOODSIG"; then
echo -e "${GREEN}✓ VALID SIGNATURE${NC}"
echo

# Extract key information
KEY_ID=$(echo "$OUTPUT" | grep "GOODSIG" | awk '{print $3}')
KEY_USER=$(echo "$OUTPUT" | grep "GOODSIG" | cut -d' ' -f4-)

echo -e "Signed by: ${GREEN}$KEY_USER${NC}"
echo -e "Key ID: ${GREEN}$KEY_ID${NC}"

# Extract signature date if available
if echo "$OUTPUT" | grep -q "VALIDSIG"; then
SIG_TIMESTAMP=$(echo "$OUTPUT" | grep "VALIDSIG" | awk '{print $5}')
if [ -n "$SIG_TIMESTAMP" ]; then
SIG_DATE=$(date -d "@$SIG_TIMESTAMP" "+%Y-%m-%d %H:%M:%S %Z" 2>/dev/null || date -r "$SIG_TIMESTAMP" "+%Y-%m-%d %H:%M:%S %Z" 2>/dev/null || echo "Unknown")
echo -e "Signature date: ${GREEN}$SIG_DATE${NC}"
fi
fi

exit 0
elif echo "$OUTPUT" | grep -q "BADSIG"; then
echo -e "${RED}✗ INVALID SIGNATURE${NC}"
echo -e "${RED}Warning:${NC} The signature does NOT match the document!"
exit 1
elif echo "$OUTPUT" | grep -q "NODATA"; then
echo -e "${RED}✗ NO DATA${NC}"
echo -e "${RED}Error:${NC} No signature data found or signature file is invalid"
exit 1
else
echo -e "${YELLOW}? UNKNOWN STATUS${NC}"
echo -e "${YELLOW}Warning:${NC} Could not determine signature status"
echo
echo "Raw output:"
echo "$OUTPUT"
exit 2
fi