Acceptance Testing Framework
This package provides a testing framework for validating vulnerability analyzers against known fixtures. It enables teams to verify that their analyzer correctly identifies vulnerabilities in container images using VEX documents.
Table of Contents
- Acceptance Testing Framework
Overview
The acceptance testing framework works by:
- Loading test fixtures from an OCI registry (images with VEX documents and expected results attached as OCI referrers)
- Running an analyzer (wrapped by the
Auditorinterface) against each fixture - Comparing the analyzer’s output against the expected results
This approach allows reproducible, automated testing of vulnerability detection without requiring access to the analyzer’s internal implementation.
Prerequisites
- Go 1.25+ installed
- Container registry access with push permissions (for creating fixtures)
Note: The integration tests use embedded PostgreSQL binaries that are downloaded automatically - no database installation required.
Quick Start
If you just want to run the existing tests against the default fixtures repository:
go test -tags=integration -v ./test/acceptance/...
The tests will automatically pull fixtures from quay.io/projectquay/clair-fixtures.
Creating Fixtures
A fixture consists of three parts:
- A container image (the thing being analyzed)
- One or more VEX documents describing vulnerabilities
- An expected results CSV defining what the analyzer should find
VEX Document Format
VEX documents must be valid CSAF 2.0
with category: csaf_vex. Here’s a minimal example:
{
"document": {
"category": "csaf_vex",
"csaf_version": "2.0",
"publisher": {
"category": "vendor",
"name": "Your Organization",
"namespace": "https://example.com"
},
"title": "CVE-2024-1234: Example vulnerability",
"tracking": {
"current_release_date": "2024-01-01T00:00:00Z",
"id": "CVE-2024-1234",
"initial_release_date": "2024-01-01T00:00:00Z",
"revision_history": [
{"date": "2024-01-01T00:00:00Z", "number": "1", "summary": "Initial"}
],
"status": "final",
"version": "1"
}
},
"product_tree": {
"branches": [
{
"category": "product_version",
"name": "mypackage-1.2.3",
"product": {
"name": "My Package 1.2.3",
"product_id": "mypackage-1.2.3",
"product_identification_helper": {
"purl": "pkg:pypi/mypackage@1.2.3"
}
}
}
]
},
"vulnerabilities": [
{
"cve": "CVE-2024-1234",
"product_status": {
"known_affected": ["mypackage-1.2.3"]
}
}
]
}
Key fields:
| Field | Description |
|---|---|
document.tracking.id | The CVE/tracking ID (must match CSV) |
product_tree.branches[].product.product_id | Product identifier (must match CSV) |
product_tree.branches[].product.product_identification_helper.purl | Package URL for matching |
vulnerabilities[].product_status.known_affected | List of affected product IDs |
vulnerabilities[].product_status.known_not_affected | List of not-affected product IDs |
Expected Results CSV
The expected results file is a CSV with three columns (no header row):
tracking_id,product_id,status
Example:
CVE-2024-1234,mypackage-1.2.3,affected
CVE-2024-5678,otherpackage-2.0.0,not_affected
CVE-2024-9999,fixedpackage-3.0.0,absent
| Status | Meaning | Test Behavior |
|---|---|---|
affected | Product is vulnerable | MUST appear in analyzer results as affected |
not_affected | Product is known to not be affected | MUST appear in analyzer results as not-affected |
absent | Product should not appear (fixed/filtered) | MUST NOT appear in analyzer results |
Lines starting with # are treated as comments.
Uploading Fixtures
Use the test/acceptance/cmd/fixture tool to create fixtures:
# Create a fixture
go run ./test/acceptance/cmd/fixture create \
-image registry.example.com/namespace/image@sha256:abc123... \
-tag fixture-name \
-vex path/to/vex.json \
-manifest path/to/expected.csv \
-repo registry.example.com/namespace/fixtures
# You can attach multiple VEX documents
go run ./test/acceptance/cmd/fixture create \
-image registry.example.com/namespace/image@sha256:abc123... \
-tag multi-vex-fixture \
-vex vex1.json \
-vex vex2.json \
-vex vex3.json \
-manifest expected.csv \
-repo registry.example.com/namespace/fixtures
# Verify the fixture was created
go run ./test/acceptance/cmd/fixture list -image registry.example.com/namespace/fixtures:fixture-name
Create Options
| Flag | Default | Description |
|---|---|---|
-image | (required) | Source image reference with digest |
-tag | (required) | Tag name for the fixture |
-vex | (required) | Path to VEX document (repeatable) |
-manifest | (required) | Path to expected results CSV |
-repo | quay.io/projectquay/clair-fixtures | Target repository |
-platform | linux/amd64 | Platform to copy (use all for multi-arch) |
Running Tests
Running Integration Tests
The integration tests automatically download and run embedded PostgreSQL binaries; no database setup required:
go test -tags=integration -v ./test/acceptance/...
Using Alternative Repository
The fixtures-repo flag can be passed to the test to run against an alternative
repository of fixtures.
go test -tags=integration -v ./test/acceptance -fixtures-repo registry.example.com/namespace/fixtures:fixture-name
Using Local OCI Layout
For testing without a registry, fixtures can be loaded from local OCI Layout directories:
acceptance.Run(ctx, t, auditor, []string{
"ocidir:///path/to/local/fixture",
})
Building Fixtures from Live VEX URLs
If you already have VEX documents hosted at known URLs (e.g. from a security
advisory feed), you can supply them directly without storing them as OCI referrers.
Use FetchVEXDocs to download the documents, populate a Fixture directly, and
pass it to Run via WithFixture. The image Reference is still pulled from a
registry for indexing.
See example_test.go for an example
(ExampleWithFixture).
This approach is useful for:
- Rapid iteration during development without pushing VEX documents to a registry
- Testing regressions in a live advisory feed
Testing with Claircore
Most teams will use the built-in claircore auditor to test their images.
See integration_test.go for a
complete example showing how to set up and run acceptance tests with the
ClaircoreAuditor.
To run:
go test -tags=integration -v ./test/acceptance/...
The test will:
- Pull each fixture from the registry
- Index the image with claircore
- Load the VEX documents attached to the image
- Match vulnerabilities against the indexed packages
- Compare results to the expected results CSV
- Report any mismatches or missing vulnerabilities
Implementing a Custom Auditor
If you’re building your own vulnerability analyzer (not using claircore), implement
the Auditor interface:
See the Auditor interface and Result type documentation.
See example_test.go for a complete, type-checked example implementation.
Media Types
| Type | Media Type | Description |
|---|---|---|
| VEX | application/csaf+json | CSAF/VEX vulnerability document |
| Expected Results | application/vnd.com.redhat.container.acceptancetest.v1+csv | Test expectations CSV |
Compressed variants (...+zstd) are also supported.