Skip to content

Commit c4c6a9b

Browse files
bugerTit Petricclaude
authored
TT-17641: Own next-generation plugin compiler workflows and image attestations (#517)
* feat: own plugin compiler workflows and image attestations * fix: use Buildx attestation-capable builder * Harden NG compiler self-test exclusion * fix(plugin-compiler): harden NG image and module handling * fix(plugin-compiler): prune unsupported Kerberos sysroot files * feat: add DHI VEX-aware Trivy scanning * feat(plugin-compiler): manage DHI toolchain base * fix(plugin-compiler): validate native Go FIPS setting * revert: drop the gromit dhi-vex scan command The DHI VEX work does not belong in gromit. Re-keying Docker Hardened Images decisions onto installed binary package identities is a publishing pipeline that produces a Trivy VEX repository, not a scan-time wrapper: consumers point Trivy at the published repository and need no gromit-side tooling at all. Reverts eec1c2b. The pipeline lives in tyk-vex-records-live. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(plugin-compiler): require the DHI-provisioned toolchain The NG compiler toolchain is no longer installable at build time. It must arrive pre-provisioned in the Docker Hardened Images customization named by BASE_IMAGE, and the Dockerfile fails closed if any expected component is missing from the base. This is a security requirement, not a convenience. Only packages Docker provisions into the customization are covered by Docker's maintenance obligation, carry +dhi versions, and have published DHI vulnerability decisions. A toolchain package apt-installed at build time would be an ordinary upstream build that nobody is obliged to patch and that no DHI advisory covers, silently widening the image's unmaintained surface. Removed with it: PREPROVISIONED_TOOLCHAIN, the pinned debian:bookworm-slim pull-request base, NG_PR_BASE_SOURCE, and the PullRequestBaseImage policy field. Pull requests now build the same base the release builds, so the compile/load gate validates the artifact that actually ships instead of a Debian stand-in. The trade-off is deliberate: changing the toolchain package list now requires Docker to rebuild the customization first. Also folded in: - consolidate plugin-compiler-ng-base.yml into the build workflow and drop the unused rewrite-imports.go, declaring both under the tyk repo's deletedfiles so generated checkouts are cleaned up - extract removeDeletedFiles, and stop continuing past a failed stat into a nil-FileInfo dereference - extend the loadtest gate and build.sh Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(plugin-compiler): let pull requests pull the private DHI base Requiring the DHI-provisioned toolchain broke pull-request builds. The customization lives in a private Docker Hub repository, but the Docker Hub login step was gated `github.event_name != 'pull_request'` -- a condition that was correct only while pull requests used the public debian:bookworm-slim fallback. Verified: an anonymous manifest fetch for tykio/dhi-busybox-plugin-compiler returns HTTP 401, while public repos on the same probe return 200. "Resolve source base digest" runs unconditionally, so every pull-request run would have failed there. Two changes: - The Docker Hub login now runs on pull requests too. The ECR steps stay gated, because only release builds push. - docker-build is skipped for pull requests raised from a fork. GitHub withholds secrets from fork runs, so such a build cannot pull the base at all; skipping it beats failing every community pull request with an opaque 401. There is still no public fallback base. The fork guard is composed as a bare expression. Splicing a ${{ }} fragment into an `if` that is already bare string-concatenates instead of evaluating, which silently always passes -- a test now asserts the rendered condition contains no ${{. Note this widens secret exposure: DOCKER_USERNAME/DOCKER_PASSWORD are now readable by same-repo pull-request runs, where previously they were not. A pull-only Docker Hub token would narrow that back and is worth a follow-up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(plugin-compiler): refresh the DHI customization before each release Docker does not rebuild a customization when packages it ADDS receive security patches. Only a base-image patch or an OCI artifact change triggers a rebuild, and this base is a minimal BusyBox runtime that Docker's own catalog reports as 0 CRITICAL / 0 HIGH / 0 MEDIUM / 0 LOW. That trigger therefore effectively never fires, while every vulnerability in the compiler image lives in an added package. Observed: the customization sat unbuilt from 2026-07-29 to 2026-08-10 while Docker published expat 2.8.2-1~deb13u1+dhi0 on 2026-07-30. The image kept shipping libexpat1 2.7.1-2+dhi5 with four HIGH findings that already had a fix. A manual rebuild moved libexpat1 to 2.8.2-1~deb13u1+dhi0 AND linux-libc-dev from 6.12.96-1+dhi0 to 6.12.101-1+dhi0, and raised +dhi coverage from 112/162 to 118/162. linux-libc-dev was never declared, which proves rebuilds resolve packages freshly rather than replaying a snapshot -- the mechanism works, nothing was triggering it. Release builds now refresh the customization before resolving the base digest. There is no supported way to ask for a rebuild: `customization build` exposes only get/list/logs, and `edit` is a no-op unless the manifest actually differs -- while still returning "Successfully updated". Confirmed deliberately: an unmodified re-apply queued no build after seven minutes. The step therefore stamps the run id into an annotation solely to make the manifest unequal. The annotation means nothing; the step should be deleted once Docker ships a real trigger. Reported as docker-hardened-images/advisories#2017. Because `edit` reports success either way, the step does not trust its exit code. It records the newest build id first and polls for a genuinely different one, so a silently discarded request is detected rather than assumed to have worked. Constraints: - Release events only. A pull request must never rewrite the shared hardened base, so the step is gated off for them and fork PRs cannot reach it at all. - continue-on-error. A refresh that fails leaves the base as fresh as it was yesterday, which is worse than current but far better than blocking a release on Docker-side behaviour we do not control. Failures raise a ::warning::, write to the step summary, and mark the step red so a persistently stale base is visible rather than silent. - Configurable, not hardcoded. `customizationid` is a policy field and the org defaults to the baseimage prefix; omitting the id removes the step entirely. The customization id is stable across rebuilds (only build ids change), so pinning it in config is safe. Also declares expat in the customization. It previously arrived only as a transitive dependency, which is exactly why it drifted unnoticed while every explicitly declared package stayed level with Docker's newest +dhi builds. * fix(plugin-compiler): degrade cleanly when the DHI CLI is absent The customization refresh failed on its first release run with: unknown flag: --org Usage: docker [OPTIONS] COMMAND [ARG...] Process completed with exit code 125 `docker dhi` is a Docker Desktop CLI plugin and is not present on hosted runners, so the first call fell through to plain `docker`, which rejected `--org`. Because that happened on the very first command, none of the step's warning or step-summary reporting ran -- the operator saw a raw error that says nothing about the actual problem. continue-on-error worked as intended: v5.15.0-alpha11 published normally, and its base was current because the customization had been rebuilt manually beforehand. But a missing dependency should announce itself, not fail obscurely. The step now checks for the CLI up front and, when it is missing, emits a ::warning:: naming the real cause and records it in the step summary before exiting. The exit is still non-zero so continue-on-error marks the step red and a persistently unrefreshed base stays visible. This does not make the refresh work in CI. Installing the plugin on the runner is a separate question, and if no standalone Linux distribution exists then automating customization refresh is not possible with the supported tooling at all -- which is worth adding to docker-hardened-images/advisories#2017. * chore: drop files committed by accident from this branch An earlier commit on this branch used `git add -A`, which swept in 42 files that were sitting untracked in the working tree and have nothing to do with the plugin compiler: an AI-metadata migration from 2026-05-21 (its scripts, CSV reports, rsync excludes and ~4000 lines of sync logs), a stray root-level config.yaml, a zellij session layout, and goal.md, a 1661-line experiment ledger from the session that preceded this work. Also drops plugin-compiler-ng-jira-ticket.md and plugin-compiler-ng-security-scanning.md. Those are about this project, but they are drafts of the ticket text rather than repository documentation, and their content now lives in TT-17641. Removed with `git rm --cached`, so the files stay on disk for whoever was using them; only the tracking goes away. Since the additions and removals are both on this branch, the files no longer appear in the pull request diff at all. .gitignore gains entries for them so the next `git add -A` cannot repeat this. Nothing under dhi/, docs/, policy/ or config/ is touched -- those are the actual subject of this branch. * fix(dhi): stop the refresh stamp from causing endless rebuilds Review of this branch found that the release-time customization refresh and the apply script undo each other. The refresh stamps `io.tyk.rebuild-trigger` into the remote manifest purely to create a difference, because Docker offers no way to request a rebuild. But EqualCustomizations only strips `id`, so after any release the apply script sees the stamped remote as different from the repository manifest, edits it to remove the stamp -- and that edit is itself a difference, which queues another rebuild. The script's "already up to date" path was dead from the first release onwards, which also contradicts this branch's own claim of idempotent apply tooling. The stamp describes nothing about the desired image, so manifest comparison now ignores it. Two tests cover it: a stamped remote compares equal, and a genuine annotation change is still a difference. Four further fixes in the refresh step, all from the same review: - An empty build list left `latest` empty, which is not equal to `before`, so the "no rebuild was queued" guard was skipped and the step reported success while having done nothing. It now treats an empty result as failure. - The annotation stamper matched the first `annotations:` anywhere in the file. A nested block, or a key like `image-annotations:`, would take the match and the new entry would be dedented out of its mapping, corrupting the manifest about to be sent to Docker. It now anchors to a top-level block, refuses to guess when several exist, and appends one when there is none. Verified against nested, decoy, absent and already-stamped inputs; all now yield valid YAML with exactly one stamp. - The failure check looked at a fixed two rows, so a failure on any further platform was missed. It now checks every row of the batch just queued, matched on their shared start timestamp. - CustomizationOrgValue read the raw BaseImage field rather than BaseImageValue, returning "" whenever only the default was configured, which rendered `--org ""`. It now uses the defaulted value and rejects a registry host such as `dhi.io`, since that is not an organization. The step also refuses to run with an empty org instead of calling the CLI with one. Also restores gofmt on policy/policy.go and policy/diff_test.go, which this branch had broken, and extends .gitignore to the two working documents removed in 6c68840 so a `git add -A` cannot bring them back. --------- Co-authored-by: Tit Petric <tit@tyk.io> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 0367dc1 commit c4c6a9b

55 files changed

Lines changed: 8712 additions & 247 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,22 @@ __pycache__
4444

4545
.idea/
4646
public/
47-
.DS_Store
47+
48+
# Local working files from unrelated migration/agent tooling. These are not part
49+
# of the project and were once committed by accident; ignoring them keeps a
50+
# `git add -A` from sweeping them back in.
51+
/goal.md
52+
/config.yaml # stray local copy; the real one is config/config.yaml
53+
/base-att.txt
54+
/ai-metadata-*.md
55+
/migration-*
56+
/migration-sync-logs/
57+
/run-migration-sync*.sh
58+
/migrate-ai-history-*.sh
59+
/replace-ai-metadata-*.sh
60+
/sync-reqforge-worktrees-*.sh
61+
/launch-agentic-sessions-*.sh
62+
/zellij-agentic-sessions-*.kdl
63+
/plugin-compiler-ng-jira-ticket.md
64+
/plugin-compiler-ng-security-scanning.md
65+
.DS_Store

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,4 @@ These files are marked with `# Generated by: gromit policy`. Never edit them dir
669669
| `GetCC target host` | Returns cross-compiler name |
670670
| `GetImages "DHRepo" "CSRepo"` | Returns image names for given registries |
671671
| `HasBuild "fips"` | Checks if a build exists |
672-
| `has "feature" .Features` | Checks if a feature is active (Sprig) |
672+
| `has "feature" .Features` | Checks if a feature is active (Sprig) |

config.yaml

Lines changed: 920 additions & 0 deletions
Large diffs are not rendered by default.

config/config.yaml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ policy:
5353
repos:
5454
# Repo specific policy for `tyk` starts here->
5555
tyk:
56+
deletedfiles:
57+
- .github/workflows/plugin-compiler-ng-base.yml
58+
- ci/images/plugin-compiler-ng/data/rewrite-imports.go
5659
# packagename is the historical name of the package. Builds
5760
# may produce artifacts named differently but the
5861
# directories and contents of the package use this name.
@@ -173,6 +176,51 @@ policy:
173176
# official images. These tests are usually required for PRs to
174177
# pass so be careful with names
175178
tests: [api]
179+
plugincompiler:
180+
depguardref: d3fa20888fa2878e877e22bb7702141217290e7c
181+
depguardif: github.event_name == 'pull_request'
182+
dockerbuildif: |-
183+
!cancelled() &&
184+
(needs.dep-guard.result == 'success' || needs.dep-guard.result == 'skipped') &&
185+
!github.event.pull_request.draft
186+
checkoutdepth: 0
187+
pullrequesttypesstyle: inline
188+
pullrequesttypes: [opened, synchronize, reopened, labeled]
189+
variants:
190+
- name: std
191+
title: tyk-plugin-compiler
192+
description: Plugin compiler for the Tyk API Gateway
193+
- name: ee
194+
imagesuffix: -ee
195+
title: tyk-plugin-compiler-ee
196+
description: Plugin compiler for the Tyk API Gateway Enterprise Edition
197+
buildtag: ee
198+
- name: fips
199+
imagesuffix: -fips
200+
title: tyk-plugin-compiler-fips
201+
description: Plugin compiler for the Tyk API Gateway FIPS Edition
202+
buildtag: ee,fips
203+
gofips140: v1.0.0
204+
nextgen:
205+
tagsuffix: -ng
206+
baseimagename: tyk-plugin-compiler-ng-base
207+
baseimagetag: latest
208+
workflowbaseimagename: tyk-plugin-compiler
209+
workflowbaseimagetag: ng-base-${{ github.sha }}
210+
baseimage: tykio/dhi-busybox-plugin-compiler:1.37.0-debian13-fips_plugin-compiler-ng-toolchain
211+
# Docker does not rebuild a customization when packages it adds are
212+
# patched. Release builds refresh it first so the compiler ships
213+
# current packages. See docker-hardened-images/advisories#2017.
214+
customizationid: cz_3gxyrz8ca7x0l
215+
glibctarget: "2.17"
216+
cross: "1"
217+
slim: "0"
218+
withcxx: "1"
219+
withgit: "1"
220+
gatewaytrimpath: "true"
221+
cearchs: amd64,arm64,s390x
222+
eearchs: amd64,arm64
223+
fipsarchs: amd64,arm64
176224
# Features common to every tyk branch. Branch entries below only
177225
# add their genuine extras (features are unioned across levels).
178226
features:
@@ -191,14 +239,72 @@ policy:
191239
- fips
192240
- ee
193241
- resolve-dashboard
242+
- plugin-compiler
243+
- plugin-compiler-ng
194244
release-5.3:
195245
buildenv: 1.24-bullseye
246+
plugincompiler:
247+
goimage: 1.23-bullseye
248+
depguardref: 2b35ab5dd4cfff21ced9d12446e9e27d10bf5785
249+
depguardif: ${{ github.event_name == 'pull_request' }}
250+
dockerbuildif: ${{ !github.event.pull_request.draft && always() && (needs.dep-guard.result == 'success' || needs.dep-guard.result == 'skipped') }}
251+
checkoutdepth: 1
252+
pullrequesttypesstyle: list
253+
pullrequesttypes: [opened, reopened, synchronize, labeled]
254+
variants:
255+
- name: std
256+
title: tyk-plugin-compiler
257+
description: Plugin compiler for the Tyk API Gateway
196258
release-5.8:
259+
plugincompiler:
260+
depguardref: 2b35ab5dd4cfff21ced9d12446e9e27d10bf5785
261+
depguardif: ${{ github.event_name == 'pull_request' }}
262+
dockerbuildif: ${{ always() && !github.event.pull_request.draft && (needs.dep-guard.result == 'success' || needs.dep-guard.result == 'skipped') }}
263+
checkoutdepth: 1
264+
pullrequesttypesstyle: inline
265+
pullrequesttypes: [opened, reopened, synchronize, labeled]
266+
variants:
267+
- name: std
268+
title: tyk-plugin-compiler
269+
description: Plugin compiler for the Tyk API Gateway
270+
- name: ee
271+
imagesuffix: -ee
272+
title: tyk-plugin-compiler-ee
273+
description: Plugin compiler for the Tyk API Gateway Enterprise Edition
274+
buildtag: ee
275+
- name: fips
276+
imagesuffix: -fips
277+
title: tyk-plugin-compiler-fips
278+
description: Plugin compiler for the Tyk API Gateway FIPS Edition
279+
buildtag: ee,fips,boringcrypto
280+
goexperiment: boringcrypto
197281
features:
198282
- fips
199283
- ee
200284
- resolve-dashboard
201285
release-5.8.15:
286+
plugincompiler:
287+
depguardref: 2b35ab5dd4cfff21ced9d12446e9e27d10bf5785
288+
depguardif: ${{ github.event_name == 'pull_request' }}
289+
dockerbuildif: ${{ always() && !github.event.pull_request.draft && (needs.dep-guard.result == 'success' || needs.dep-guard.result == 'skipped') }}
290+
checkoutdepth: 1
291+
pullrequesttypesstyle: inline
292+
pullrequesttypes: [opened, reopened, synchronize, labeled]
293+
variants:
294+
- name: std
295+
title: tyk-plugin-compiler
296+
description: Plugin compiler for the Tyk API Gateway
297+
- name: ee
298+
imagesuffix: -ee
299+
title: tyk-plugin-compiler-ee
300+
description: Plugin compiler for the Tyk API Gateway Enterprise Edition
301+
buildtag: ee
302+
- name: fips
303+
imagesuffix: -fips
304+
title: tyk-plugin-compiler-fips
305+
description: Plugin compiler for the Tyk API Gateway FIPS Edition
306+
buildtag: ee,fips,boringcrypto
307+
goexperiment: boringcrypto
202308
features:
203309
- fips
204310
- ee

config/lint_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import (
1111
)
1212

1313
var nonScalarKeys = map[string]bool{
14-
"repos": true,
15-
"branches": true,
16-
"builds": true,
17-
"features": true,
18-
"deletedfiles": true,
19-
"tests": true,
14+
"repos": true,
15+
"branches": true,
16+
"builds": true,
17+
"features": true,
18+
"deletedfiles": true,
19+
"tests": true,
20+
"plugincompiler": true,
2021
}
2122

2223
// TestConfigRedundancy keeps config.yaml honest about its own cascade.

dhi/README.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Docker Hardened Image Customizations
2+
3+
Gromit owns the Docker-managed base used by the next-generation Tyk plugin
4+
compiler. The customization installs the compiler's direct package requirements
5+
on the non-dev Debian 13 FIPS BusyBox image. Docker resolves the transitive
6+
closure and publishes the customized image with its own signed SBOM,
7+
provenance, and VEX attestations.
8+
9+
The Docker token remains in the local or CI Docker/DHI credential store. It
10+
must not be added to this repository.
11+
12+
## FIPS scopes
13+
14+
The customized base and the generated plugin use separate cryptographic
15+
modules:
16+
17+
- the customized DHI contains Docker's OpenSSL FIPS Provider 3.1.2, which is
18+
active at runtime;
19+
- the current Tyk FIPS plugin compiler sets `GOFIPS140=v1.0.0`, linking the
20+
native Go Cryptographic Module covered by CMVP Certificate #5247 into the
21+
plugin; it does not use legacy Go+BoringCrypto;
22+
- older release branches can still select Go+BoringCrypto through their
23+
Gromit branch variables.
24+
25+
Docker has not published its FIPS predicate for the exact customized image
26+
subject. That is an evidence gap for claiming that the customized compiler
27+
container is Docker-FIPS-attested. It does not mean the generated Go plugin is
28+
non-FIPS, and it does not block an alpha unless that exact container claim is
29+
an alpha requirement.
30+
31+
## Apply
32+
33+
```bash
34+
./dhi/apply-plugin-compiler-customization.sh
35+
```
36+
37+
The wrapper creates the customization when it does not exist and edits the
38+
existing customization only when its normalized manifest differs. Override
39+
the organization with `DHI_ORG`; `DHI_DESTINATION` defaults to
40+
`${DHI_ORG}/dhi-busybox-plugin-compiler`.
41+
42+
Current remote customization:
43+
44+
```text
45+
organization: tykio
46+
destination: tykio/dhi-busybox-plugin-compiler
47+
name: plugin compiler ng toolchain
48+
id: cz_3gxyrz8ca7x0l
49+
tag: 1.37.0-debian13-fips_plugin-compiler-ng-toolchain
50+
index: sha256:8a8967f03d2243d88659256e8a3ca3f5a7b009a4b522e5608f1facfed9be3733
51+
amd64: sha256:58369d0f3051eaf1c7478465ddd2c36aa582c437f6d66fbc933e25de5a7dc0df
52+
arm64: sha256:603c7940ecc930f763cd869e98285c1952e40885a2bf549ce7aadf9325a3381f
53+
```
54+
55+
## Monitor
56+
57+
```bash
58+
docker dhi customization build list cz_3gxyrz8ca7x0l --org tykio
59+
docker dhi customization build get cz_3gxyrz8ca7x0l <build-id> --org tykio
60+
docker dhi customization build logs cz_3gxyrz8ca7x0l <build-id> --org tykio
61+
```
62+
63+
Do not update Gromit's plugin compiler source-base reference until both amd64
64+
and arm64 customization builds succeed.
65+
66+
## Verify
67+
68+
Resolve the rolling customization tag on every promotion and pin the resulting
69+
multi-platform index digest in `config/config.yaml`.
70+
71+
```bash
72+
REPO=tykio/dhi-busybox-plugin-compiler
73+
TAG=1.37.0-debian13-fips_plugin-compiler-ng-toolchain
74+
INDEX=sha256:8a8967f03d2243d88659256e8a3ca3f5a7b009a4b522e5608f1facfed9be3733
75+
REF="${REPO}:${TAG}@${INDEX}"
76+
REMOTE="registry://${REPO}@${INDEX}"
77+
78+
docker buildx imagetools inspect "$REF"
79+
docker scout attestation list --platform linux/amd64 "$REMOTE"
80+
docker scout cves --platform linux/amd64 --only-severity critical,high "$REMOTE"
81+
82+
trivy image \
83+
--image-src remote \
84+
--platform linux/amd64 \
85+
--scanners vuln \
86+
--severity HIGH,CRITICAL \
87+
"${REPO}@${INDEX}"
88+
89+
grype \
90+
"registry:${REPO}@${INDEX}" \
91+
--platform linux/amd64 \
92+
--fail-on high
93+
```
94+
95+
Do not add `docker scout vex get` to the customer gate yet. Docker Scout
96+
`1.20.4` and `1.23.1` both verify the first DHI signature and then panic in
97+
`VEXExportProcessor`, leaving no VEX output. The three underlying OpenVEX OCI
98+
artifacts are present and independently verify against Docker's DHI key, but
99+
passing those raw in-toto predicates directly to Trivy does not reproduce
100+
Scout's required package-product projection.
101+
102+
Package inclusion makes findings eligible for Docker's customized-image
103+
assessment; it does not imply that every finding is `not_affected`. Verify that
104+
the SBOM contains the complete Git and compiler dependency closures and review
105+
every VEX disposition before promotion.
106+
107+
The Go toolchain, Gateway source, and compatibility glibc sysroots are added by
108+
the downstream compiler build. They are outside this Debian package boundary
109+
and require their own SBOM and vulnerability checks.
110+
111+
## Verification status
112+
113+
The final 2026-07-28 build passed these gates:
114+
115+
- amd64 and arm64 customization builds completed successfully;
116+
- 207 packages are present in Docker's signed SBOM;
117+
- native and cross C/C++ compilers for amd64, arm64, and s390x execute;
118+
- the OpenSSL FIPS provider is active;
119+
- Trivy 0.72 reports 17 Critical and 75 High without VEX;
120+
- the downstream FIPS compiler builds and loads an amd64 native-Go-FIPS plugin
121+
with `GOFIPS140=v1.0.0`, validates an arm64 plugin, and excludes the
122+
test-only Gateway binary from the production image.
123+
124+
The following are open upstream gates and must not be represented as passing:
125+
126+
- the custom image has the `com.docker.dhi.compliance=fips,stig,cis` label and
127+
an active OpenSSL FIPS provider, but lacks Docker's signed
128+
`https://docker.com/dhi/fips/v0.1` attestation for the customized subject;
129+
this limits the compiler-container claim, not the generated plugin's native
130+
Go FIPS mode;
131+
- anonymous Scout VEX retrieval for the custom repository returns
132+
`UNAUTHORIZED`, so customers currently need Docker registry access to fetch
133+
the live custom-product document;
134+
- authenticated `docker scout vex get` panics in both Scout `1.20.4` and
135+
`1.23.1`, so there is currently no supported customer command that exports
136+
the live custom-product VEX for Trivy;
137+
- Grype 0.116 reports four active High libssh2 issues
138+
(`CVE-2026-66032` through `CVE-2026-66035`; eight matches). Debian currently
139+
marks them vulnerable, Docker VEX has no disposition for them, and
140+
`1.11.1-1+dhi3` is the newest DHI package. They must be fixed upstream or
141+
explicitly assessed; they cannot be legitimately suppressed.

0 commit comments

Comments
 (0)