Skip to content

Commit c2fd2e0

Browse files
authored
feat(vex): retrieve VEX attestations from OCI registries (#7249)
Signed-off-by: knqyf263 <[email protected]>
1 parent 4a2f492 commit c2fd2e0

19 files changed

+701
-1244
lines changed

docs/docs/references/configuration/cli/trivy_filesystem.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ trivy filesystem [flags] PATH
9191
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
9292
--trace enable more verbose trace output for custom queries
9393
--username strings username. Comma-separated usernames allowed.
94-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
94+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
9595
```
9696

9797
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_image.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ trivy image [flags] IMAGE_NAME
111111
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
112112
--trace enable more verbose trace output for custom queries
113113
--username strings username. Comma-separated usernames allowed.
114-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
114+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
115115
```
116116

117117
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_kubernetes.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ trivy kubernetes [flags] [CONTEXT]
105105
--tolerations strings specify node-collector job tolerations (example: key1=value1:NoExecute,key2=value2:NoSchedule)
106106
--trace enable more verbose trace output for custom queries
107107
--username strings username. Comma-separated usernames allowed.
108-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
108+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
109109
```
110110

111111
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_repository.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
9191
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
9292
--trace enable more verbose trace output for custom queries
9393
--username strings username. Comma-separated usernames allowed.
94-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
94+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
9595
```
9696

9797
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_rootfs.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ trivy rootfs [flags] ROOTDIR
9292
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
9393
--trace enable more verbose trace output for custom queries
9494
--username strings username. Comma-separated usernames allowed.
95-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
95+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
9696
```
9797

9898
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_sbom.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ trivy sbom [flags] SBOM_PATH
6363
-t, --template string output template
6464
--token string for authentication in client/server mode
6565
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
66-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
66+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
6767
```
6868

6969
### Options inherited from parent commands

docs/docs/references/configuration/cli/trivy_vm.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ trivy vm [flags] VM_IMAGE
7878
--tf-exclude-downloaded-modules exclude misconfigurations for downloaded terraform modules
7979
--token string for authentication in client/server mode
8080
--token-header string specify a header name for token in client/server mode (default "Trivy-Token")
81-
--vex strings [EXPERIMENTAL] VEX sources ("repo" or file path)
81+
--vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path)
8282
```
8383

8484
### Options inherited from parent commands

docs/docs/supply-chain/vex/index.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,21 @@ Trivy currently supports two methods for utilizing VEX:
1212

1313
1. [VEX Repository](./repo.md)
1414
2. [Local VEX Files](./file.md)
15+
3. [VEX Attestation](./oci.md)
1516

1617
### Enabling VEX
1718
To enable VEX, use the `--vex` option.
1819
You can specify the method to use:
1920

2021
- To enable the VEX Repository: `--vex repo`
2122
- To use a local VEX file: `--vex /path/to/vex-document.json`
23+
- To enable VEX attestation discovery in OCI registry: `--vex oci`
2224

2325
```bash
2426
$ trivy image ghcr.io/aquasecurity/trivy:0.52.0 --vex repo
2527
```
2628

27-
You can enable both methods simultaneously.
29+
You can enable these methods simultaneously.
2830
The order of specification determines the priority:
2931

3032
- `--vex repo --vex /path/to/vex-document.json`: VEX Repository has priority

docs/docs/supply-chain/vex/oci.md

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Discover VEX Attestation in OCI Registry
2+
3+
!!! warning "EXPERIMENTAL"
4+
This feature might change without preserving backwards compatibility.
5+
6+
Trivy can discover VEX attestations for container images.
7+
This feature allows you to automatically use VEX during container image scanning.
8+
9+
## How It Works
10+
11+
Trivy can automatically discover and utilize VEX attestations for container images during scanning by using the `--vex oci` flag.
12+
This process enhances vulnerability detection results by incorporating the information from the VEX attestation.
13+
14+
To use this feature, follow these three steps:
15+
16+
1. Create a VEX document
17+
2. Generate and upload a VEX attestation to an OCI registry
18+
3. Use the VEX attestation with Trivy
19+
20+
Steps 1 and 2 are not necessary if you are trying to scan a third-party container image and already have VEX attestation attached.
21+
22+
Let's go through each step in detail.
23+
24+
!!! note
25+
In the following examples, the `cosign` command will write an attestation to a target OCI registry, so you must have permission to write.
26+
If you want to avoid writing an OCI registry and only want to see an attestation, add the `--no-upload` option to the cosign command.
27+
28+
### Step 1: Create a VEX Document
29+
30+
Currently, Trivy does not have a built-in feature to create VEX documents, so you need to create them manually.
31+
You can refer to the [OpenVEX section](./file.md#openvex) for guidance on creating VEX files.
32+
33+
For container image vulnerabilities, the product ID should be the OCI type in the [PURL][purl] format.
34+
For example:
35+
36+
```
37+
pkg:oci/trivy?repository_url=ghcr.io/aquasecurity/trivy
38+
```
39+
40+
This product ID applies the VEX statement to all tags of the `ghcr.io/aquasecurity/trivy` container image.
41+
If you want to declare a statement for a specific digest only, you can use:
42+
43+
```
44+
pkg:oci/trivy@sha256:5bd5ab35814f86783561603ebb35d5d5d99006dcdcd5c3f828ea1afb4c12d159?repository_url=ghcr.io/aquasecurity/trivy
45+
```
46+
47+
!!! note
48+
Using an image tag, like `pkg:oci/trivy?repository_url=ghcr.io/aquasecurity/trivy&tag=0.50.0`, is not supported in the product ID at the moment.
49+
50+
Next, specify vulnerable packages as subcomponents, such as `pkg:apk/alpine/busybox`.
51+
You can also include the package version and other [qualifiers][qualifiers] (e.g., `arch`) to limit statements, like `pkg:apk/alpine/[email protected]?arch=x86`.
52+
53+
Lastly, include the vulnerability IDs.
54+
55+
Here's an example VEX document:
56+
57+
```json
58+
{
59+
"@context": "https://openvex.dev/ns/v0.2.0",
60+
"@id": "https://openvex.dev/docs/public/vex-2e67563e128250cbcb3e98930df948dd053e43271d70dc50cfa22d57e03fe96f",
61+
"author": "Aqua Security",
62+
"timestamp": "2024-07-30T19:07:16.853479631-06:00",
63+
"version": 1,
64+
"statements": [
65+
{
66+
"vulnerability": {
67+
"name": "CVE-2023-42363"
68+
},
69+
"products": [
70+
{
71+
"@id": "pkg:oci/trivy?repository_url=ghcr.io/aquasecurity/trivy",
72+
"subcomponents": [
73+
{"@id": "pkg:apk/alpine/busybox"},
74+
{"@id": "pkg:apk/alpine/busybox-binsh"}
75+
]
76+
}
77+
],
78+
"status": "not_affected",
79+
"justification": "vulnerable_code_cannot_be_controlled_by_adversary",
80+
"impact_statement": "awk is not used"
81+
}
82+
]
83+
}
84+
```
85+
86+
You can also refer to [Trivy's example](https://github.com/aquasecurity/trivy/blob/4e54a7e84c33c1be80c52c6db78c634bc3911715/.vex/oci.openvex.json) for more inspiration.
87+
88+
### Step 2: Generate and Upload a VEX Attestation to an OCI Registry
89+
90+
You can use the [Cosign command](https://docs.sigstore.dev/verifying/attestation/) to generate and upload the VEX attestation.
91+
Cosign offers methods both with and without keys.
92+
For detailed instructions, please refer to the Cosign documentation.
93+
94+
To generate and attach a VEX attestation to your image, use the following command:
95+
96+
```
97+
$ cosign attest --predicate oci.openvex.json --type openvex <IMAGE>
98+
```
99+
100+
Note that this command attaches the attestation only to the specified image tag.
101+
If needed, repeat the process for other tags and digests.
102+
103+
### Step 3: Use VEX Attestation with Trivy
104+
105+
Once you've attached the VEX attestation to the container image, Trivy can automatically discover and use it during scanning.
106+
Simply add the `--vex oci` flag when scanning a container image:
107+
108+
```
109+
$ trivy image --vex oci <IMAGE>
110+
```
111+
112+
To see which vulnerabilities were filtered by the VEX attestation, use the `--show-suppressed` flag:
113+
114+
```
115+
$ trivy image --vex oci --show-suppressed <IMAGE>
116+
```
117+
118+
The `<IMAGE>` specified in these commands must be the same as the one to which you attached the VEX attestation.
119+
120+
[purl]: https://github.com/package-url/purl-spec
121+
[qualifiers]: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst

go.mod

+30-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ require (
2323
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
2424
github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d
2525
github.com/aquasecurity/table v1.8.0
26-
github.com/aquasecurity/testdocker v0.0.0-20240613070307-2c3868d658ac
26+
github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8
2727
github.com/aquasecurity/tml v0.6.1
2828
github.com/aquasecurity/trivy-checks v0.13.0
2929
github.com/aquasecurity/trivy-db v0.0.0-20240718084044-d23a6ca8ba04
@@ -75,6 +75,7 @@ require (
7575
github.com/liamg/iamgo v0.0.9
7676
github.com/liamg/jfather v0.0.7
7777
github.com/liamg/memoryfs v1.6.0
78+
github.com/magefile/mage v1.15.0
7879
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac
7980
github.com/masahiro331/go-ebs-file v0.0.0-20240112135404-d5fbb1d46323
8081
github.com/masahiro331/go-ext4-filesystem v0.0.0-20231208112839-4339555a0cd4
@@ -90,6 +91,7 @@ require (
9091
github.com/open-policy-agent/opa v0.66.0
9192
github.com/opencontainers/go-digest v1.0.0
9293
github.com/opencontainers/image-spec v1.1.0
94+
github.com/openvex/discovery v0.1.0
9395
github.com/openvex/go-vex v0.2.5
9496
github.com/owenrumney/go-sarif/v2 v2.3.3
9597
github.com/owenrumney/squealer v1.2.3
@@ -133,8 +135,6 @@ require (
133135
sigs.k8s.io/yaml v1.4.0
134136
)
135137

136-
require github.com/magefile/mage v1.15.0
137-
138138
require (
139139
cloud.google.com/go v0.112.1 // indirect
140140
cloud.google.com/go/compute/metadata v0.3.0 // indirect
@@ -182,6 +182,7 @@ require (
182182
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
183183
github.com/beorn7/perks v1.0.1 // indirect
184184
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
185+
github.com/blang/semver v3.5.1+incompatible // indirect
185186
github.com/briandowns/spinner v1.23.0 // indirect
186187
github.com/cespare/xxhash/v2 v2.2.0 // indirect
187188
github.com/chai2010/gettext-go v1.0.2 // indirect
@@ -198,9 +199,12 @@ require (
198199
github.com/containerd/typeurl/v2 v2.1.1 // indirect
199200
github.com/cpuguy83/dockercfg v0.3.1 // indirect
200201
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
202+
github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect
201203
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
202204
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
203205
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
206+
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
207+
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
204208
github.com/distribution/reference v0.6.0 // indirect
205209
github.com/dlclark/regexp2 v1.4.0 // indirect
206210
github.com/docker/cli v27.0.3+incompatible // indirect
@@ -218,6 +222,7 @@ require (
218222
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
219223
github.com/felixge/httpsnoop v1.0.4 // indirect
220224
github.com/fsnotify/fsnotify v1.7.0 // indirect
225+
github.com/go-chi/chi v4.1.2+incompatible // indirect
221226
github.com/go-errors/errors v1.4.2 // indirect
222227
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
223228
github.com/go-git/go-billy/v5 v5.5.0 // indirect
@@ -234,16 +239,17 @@ require (
234239
github.com/go-openapi/spec v0.21.0 // indirect
235240
github.com/go-openapi/swag v0.23.0 // indirect
236241
github.com/go-openapi/validate v0.24.0 // indirect
237-
github.com/go-test/deep v1.1.0 // indirect
238242
github.com/gobwas/glob v0.2.3 // indirect
239243
github.com/goccy/go-yaml v1.9.5 // indirect
240244
github.com/gofrs/uuid v4.3.1+incompatible // indirect
241245
github.com/gogo/protobuf v1.3.2 // indirect
242246
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
243247
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
244248
github.com/golang/protobuf v1.5.4 // indirect
249+
github.com/golang/snappy v0.0.4 // indirect
245250
github.com/google/btree v1.1.2 // indirect
246-
github.com/google/gnostic-models v0.6.8 // indirect
251+
github.com/google/certificate-transparency-go v1.1.8 // indirect
252+
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
247253
github.com/google/go-cmp v0.6.0 // indirect
248254
github.com/google/go-querystring v1.1.0 // indirect
249255
github.com/google/gofuzz v1.2.0 // indirect
@@ -260,12 +266,13 @@ require (
260266
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
261267
github.com/hashicorp/go-safetemp v1.0.0 // indirect
262268
github.com/hashicorp/golang-lru v0.6.0 // indirect
263-
github.com/hashicorp/hcl v1.0.0 // indirect
269+
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
264270
github.com/hashicorp/terraform-json v0.22.1 // indirect
265271
github.com/huandu/xstrings v1.4.0 // indirect
266-
github.com/imdario/mergo v0.3.15 // indirect
272+
github.com/imdario/mergo v0.3.16 // indirect
267273
github.com/inconshreveable/mousetrap v1.1.0 // indirect
268274
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
275+
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect
269276
github.com/jmespath/go-jmespath v0.4.0 // indirect
270277
github.com/jmoiron/sqlx v1.3.5 // indirect
271278
github.com/josharian/intern v1.0.0 // indirect
@@ -274,6 +281,7 @@ require (
274281
github.com/klauspost/compress v1.17.9 // indirect
275282
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
276283
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
284+
github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect
277285
github.com/lib/pq v1.10.9 // indirect
278286
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
279287
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
@@ -303,6 +311,7 @@ require (
303311
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
304312
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
305313
github.com/ncruces/go-strftime v0.1.9 // indirect
314+
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
306315
github.com/oklog/ulid v1.3.1 // indirect
307316
github.com/opencontainers/runtime-spec v1.2.0 // indirect
308317
github.com/opencontainers/selinux v1.11.0 // indirect
@@ -316,30 +325,38 @@ require (
316325
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
317326
github.com/prometheus/client_golang v1.19.1 // indirect
318327
github.com/prometheus/client_model v0.6.1 // indirect
319-
github.com/prometheus/common v0.48.0 // indirect
328+
github.com/prometheus/common v0.51.1 // indirect
320329
github.com/prometheus/procfs v0.15.1 // indirect
321330
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
322331
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
323-
github.com/rivo/uniseg v0.2.0 // indirect
332+
github.com/rivo/uniseg v0.4.4 // indirect
324333
github.com/rubenv/sql-migrate v1.5.2 // indirect
325334
github.com/russross/blackfriday/v2 v2.1.0 // indirect
326335
github.com/sagikazarmark/locafero v0.4.0 // indirect
327336
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
328337
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
338+
github.com/sassoftware/relic v7.2.1+incompatible // indirect
329339
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
330340
github.com/shibumi/go-pathspec v1.3.0 // indirect
331341
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
332342
github.com/shoenig/go-m1cpu v0.1.6 // indirect
333343
github.com/shopspring/decimal v1.3.1 // indirect
344+
github.com/sigstore/cosign/v2 v2.2.4 // indirect
345+
github.com/sigstore/sigstore v1.8.3 // indirect
346+
github.com/sigstore/timestamp-authority v1.2.2 // indirect
334347
github.com/skeema/knownhosts v1.2.2 // indirect
335348
github.com/sourcegraph/conc v0.3.0 // indirect
336349
github.com/spf13/afero v1.11.0 // indirect
337350
github.com/stretchr/objx v0.5.2 // indirect
338351
github.com/subosito/gotenv v1.6.0 // indirect
352+
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
339353
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
354+
github.com/theupdateframework/go-tuf v0.7.0 // indirect
355+
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
340356
github.com/tklauser/go-sysconf v0.3.13 // indirect
341357
github.com/tklauser/numcpus v0.7.0 // indirect
342358
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect
359+
github.com/transparency-dev/merkle v0.0.2 // indirect
343360
github.com/ulikunitz/xz v0.5.11 // indirect
344361
github.com/vbatts/tar-split v0.11.5 // indirect
345362
github.com/xanzy/ssh-agent v0.3.3 // indirect
@@ -371,6 +388,7 @@ require (
371388
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
372389
google.golang.org/grpc v1.64.0 // indirect
373390
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
391+
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
374392
gopkg.in/inf.v0 v0.9.1 // indirect
375393
gopkg.in/ini.v1 v1.67.0 // indirect
376394
gopkg.in/warnings.v0 v0.1.2 // indirect
@@ -397,3 +415,6 @@ require (
397415
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
398416
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
399417
)
418+
419+
// cf. https://github.com/openvex/discovery/pull/40
420+
replace github.com/openvex/discovery => github.com/knqyf263/discovery v0.1.1-0.20240726113521-97873005fd03

0 commit comments

Comments
 (0)