Skip to content

fix(deps): bump github.com/cilium/ebpf from 0.11.0 to 0.22.0 in the gomod-security group across 1 directory - #385

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/go_modules/gomod-security-ce6382dffe
Closed

fix(deps): bump github.com/cilium/ebpf from 0.11.0 to 0.22.0 in the gomod-security group across 1 directory#385
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/go_modules/gomod-security-ce6382dffe

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 19, 2026

Copy link
Copy Markdown
Contributor

Bumps the gomod-security group with 1 update in the / directory: github.com/cilium/ebpf.

Updates github.com/cilium/ebpf from 0.11.0 to 0.22.0

Release notes

Sourced from github.com/cilium/ebpf's releases.

v0.22.0: Linux 7.1 compat, BPF tokens and vmlinux BTF caching changes

Hi everyone! Today we announce the v0.22.0 release of ebpf-go. We ship Linux 7.1 compatibility, older versions of the library will not work on 7.1 kernels and above, so please upgrade if you are targeting the latest releases of Linux. We also made a breaking change to BTF caching, please read those notes. And of course a few fixes, improvements and minor features.

Kernel 7.1 compatibility

In kernel 7.1 the BTF header was extended to introduce a new feature called BTF layout. This change caused our BTF parser to fail when parsing vmlinux for this kernel. This has been fixed in this latest release, we recommend upgrading to this latest release to avoid breakage on 7.1 and newer kernels.

See cilium/ebpf#2042 for details. Special thanks to @​Capricornus007 for making the bug report that allowed us to fix this in a timely manner.

BPF token support

Some BPF-related actions require the user to have root privileges (CAP_SYS_ADMIN). One example is loading and attaching programs that can inspect kernel memory. In some environments, you may want to permit a known good process to load such BPF programs, but you don't want to grant it CAP_SYS_ADMIN to avoid privilege escalation if that process gets compromised.

BPF tokens are a mechanism that allows a privileged process to delegate fine-grained BPF capabilities to an unprivileged process. The process of delegating is complex and typically handled by a container runtime such as LXC or a process manager like systemd. This part of the handshake is currently out of scope of ebpf-go, as the library is not in charge of process creation where this delegation takes place.

However, the consuming side is what's included in this release. ebpf-go will automatically detect when the current process is running in a namespace where a BPF token is provided, and will automatically try to obtain an use it for interacting with the BPF syscall. Unlike libbpf, this currently requires no extra configuration on behalf of the application.

See cilium/ebpf#1953 for more details.

BTF cache changes

Package btf used to cache kernel (vmlinux) BTF specs globally. This is a significant time gain when loading multiple Collections in a row. However, doing so comes at a fairly significant memory cost (~20 MiB), so users could flush this cache with btf.FlushKernelSpec. Unfortunately, the caching behaviour being opt-out means users would typically discover it while investigating memory usage, and would then have to find an appropriate time during execution to call the flush function. This was always a band-aid for something we didn't have a clear solution to.

With this update, we've removed the global cache and the btf.FlushKernelSpec function, which may slow down subsequent collection loading on busy systems. To opt back in, users can now maintain their own cache object, obtained from btf.NewCache and pass it to NewCollectionWithOptions via CollectionOptions.Cache. Typically, you would put this in a global variable in a bpf-related package in your application, or keep it around in function scope if you load multiple collections in a row.

See cilium/ebpf#1988 for more details. Thank you @​matthyx for these changes.

New features

Bug fixes and improvements

... (truncated)

Commits
  • e55144e btf: Add BTF layout header parsing
  • d37ad9c struct_ops_test: Fix TestCreateStructOpsMapSpecSimple
  • 5e8bcc7 btf: Remove vmlinux dedup test
  • f1eb026 Update kernel dependencies to 7.1
  • 970a97d CODEOWNERS: allow reviewers to merge docs/, add rgo3 to link/
  • 7be98ef variable: reject offsets that overflow uint32 bounds
  • b404658 build(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1
  • 63647bc build(deps): bump mkdocs-git-revision-date-localized-plugin
  • e30ccb7 memory: use unsafe.Add to align unsafe memory instead of uintptr conversion
  • 0e35955 Makefile: pre-create GOCACHE, GOPATH and GOMODCACHE for podman
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions
    You can disable automated security fix PRs for this repo from the Security Alerts page.

Bumps the gomod-security group with 1 update in the / directory: [github.com/cilium/ebpf](https://github.com/cilium/ebpf).


Updates `github.com/cilium/ebpf` from 0.11.0 to 0.22.0
- [Release notes](https://github.com/cilium/ebpf/releases)
- [Commits](cilium/ebpf@v0.11.0...v0.22.0)

---
updated-dependencies:
- dependency-name: github.com/cilium/ebpf
  dependency-version: 0.22.0
  dependency-type: indirect
  dependency-group: gomod-security
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file priority: high High priority security Security-advisory dependency fix — merge-first labels Aug 19, 2026
@github-actions

Copy link
Copy Markdown

Semgrep Scan Results

Repository: api | Commit: cf7c328

Check Status Details
⚠️ Semgrep Warning 2 warning(s), 6 total

Scanned at 2026-08-19 18:52 UTC

@github-actions

Copy link
Copy Markdown

Security Scan Results

Repository: api | Commit: cf7c328

Check Status Details
✅ Secret Scan Pass No secrets detected
⚠️ Dependencies (Trivy) High 2 high, 3 total
⚠️ Dependencies (Grype) High 2 high, 3 total
📦 SBOM Generated 523 components (CycloneDX)

Scanned at 2026-08-19 18:53 UTC

@github-actions

Copy link
Copy Markdown

📊 Statement coverage

Measured on the documented included set (see docs/TESTING.md → Coverage scope). Observe-only — no regression gate is enforced yet.

Scope This PR main baseline Δ
Included set (Gold-tier denominator) 89.6% 89.6% +0.0 pp
Full set (whole repo, transparency) 28.5% 28.5% +0.0 pp

Baseline: main @ e1f5c9d

@Cre-eD

Cre-eD commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Superseded by #387, which makes the same cilium/ebpf 0.11.0 → 0.22.0 bump plus the fallout this PR would have hit on its own.

cilium/ebpf v0.22.0 names honnef.co/go/tools v0.7.0 in its own go.mod, so MVS raises it from v0.6.1. golangci-lint v1.64.8 does not compile against v0.7.0's analysis API — it panics mid-run and exits 7:

typedness: panic during analysis: interface conversion: interface {} is nil, not *buildir.IR
  honnef.co/go/tools@v0.7.0/analysis/facts/typedness/typedness.go:59

That fails the golangci-lint run step in branch.yaml / push.yaml / branch-preview.yaml. #387 pins honnef back with a replace directive (ebpf needs staticcheck for its CI, not for anything we compile, and a require line loses to ebpf's) and carries the removal condition in the go.mod comment.

#387 also closes GO-2026-6179 and GO-2026-6180 (golang.org/x/mod v0.38.0 → v0.40.0), which Dependabot did not raise an alert for but OpenSSF Scorecard, osv-scanner and trivy all report. Closing this one.

@Cre-eD Cre-eD closed this Aug 21, 2026
@dependabot @github

dependabot Bot commented on behalf of github Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

This pull request was built based on a group rule. Closing it will not ignore any of these versions in future pull requests.

To ignore these dependencies, configure ignore rules in dependabot.yml

@dependabot
dependabot Bot deleted the dependabot/go_modules/gomod-security-ce6382dffe branch August 21, 2026 07:27
Cre-eD added a commit that referenced this pull request Aug 21, 2026
…old bar it claimed

OpenSSF Scorecard's Vulnerabilities check reported three advisories. All
three land on dev-tool-only modules pulled in through tools.go, and all
three are fixable upstream, so they are fixed rather than VEX'd:

  golang.org/x/mod      v0.38.0 -> v0.40.0   GO-2026-6179, GO-2026-6180 (HIGH)
  github.com/cilium/ebpf v0.11.0 -> v0.22.0  GO-2026-6238 (LOW)

Neither could be fixed by bumping its parent: gofumpt v0.11.0 (latest)
still requires x/mod v0.38.0, and delve v1.27.1 (latest) still requires
ebpf v0.11.0. `go list -deps ./...` links zero packages from either
module into anything we ship, but a non-breaking upstream fix exists, and
VEX is for findings that cannot be fixed.

osv-scanner and trivy fs both go from 3 findings to 0.

The ebpf bump has fallout worth calling out. ebpf v0.22.0 names
honnef.co/go/tools v0.7.0 in its own go.mod, MVS raises it, and
golangci-lint v1.64.8 does not compile against v0.7.0's analysis API --
it panics mid-run ("typedness: panic during analysis: interface
conversion: interface {} is nil, not *buildir.IR") and exits 7, failing
the lint step in branch.yaml / push.yaml. ebpf needs staticcheck for ITS
CI, not for anything we compile, and a require line loses to ebpf's, so
honnef is pinned back with a replace directive. Dependabot #385 makes the
same ebpf bump and would have broken lint on main on its own.

Images, all four rebuilt with --no-cache and rescanned:

  caddy           11 HIGH + 1 MEDIUM -> 1 MEDIUM
  cloud-helpers   8 HIGH             -> 0
  github-actions  17 HIGH            -> unchanged (Google's gcloud binaries)
  kubectl         14 HIGH + 3 MEDIUM -> unchanged (upstream kubectl binary)

caddy: the pinned 2.11.4-builder digest shipped Go 1.26.5 and the tag has
since been rebuilt with Go 1.26.7. Since xcaddy in the builder stage
produces the binary COPY --from=builder puts into the runtime image, the
builder's toolchain IS the shipped stdlib -- refreshing the digest alone
closed 8 stdlib CVEs. Three xcaddy --replace directives lift Caddy's own
vendored x/net, x/text and grpc past CVE-2026-46600, CVE-2026-56852 and
GHSA-hrxh-6v49-42gf. --replace and not --with, because --with also writes
a blank import and none of those modules has a package at its root.

cloud-helpers: every finding was in /usr/local/bin/aws-lambda-rie, the
base image's local-testing Runtime Interface Emulator. /lambda-entrypoint.sh
execs it only when AWS_LAMBDA_RUNTIME_API is unset, and our ENTRYPOINT
replaces that script outright, so it never runs -- and the debug path that
does use a RIE (welder run debug-aws-cloud-helpers) is runOn: host and uses
the host's copy. Deleting it is the fix, not a suppression. Image now
scans clean and the binary still starts.

Deferred: cel-go 0.28.1 -> 0.29.0 (MEDIUM, GHSA-gcjh-h69q-9w9g) inside
the caddy binary. v0.29.0 renames interpreter.Interpretable to
InterpretableV2 and Caddy 2.11.4's celmatcher.go does not compile against
it -- an upstream code change. Reachability and the closing condition are
recorded in a caddy.Dockerfile comment so the next digest refresh does not
silently add it to the --replace list and break the build.

Documented unfixable, each measured rather than assumed: kubectl's own
binary (pinned digest and current latest are both v1.36.3 with identical
findings, so the pin is left alone), the gcloud SDK binaries (579.0.0 and
581.0.0 both ship gcloud-crc32c built with go1.26.5, so bumping the pin
buys nothing), and the lambda base digest, which is deliberately NOT
refreshed because the currently-tagged one is worse (30 HIGH vs 8).

VEX: all three statements re-triaged against the current tree with fresh
evidence, none flipped, document bumped to version 4. No new suppression
was added anywhere -- no .trivyignore, no new VEX statement, no new
osv-scanner.toml entry.

Coverage: docs/TESTING.md claimed the Gold-tier test_statement_coverage90
criterion was Met. It was not -- the main baseline reads 89.6%. Seven test
files take the included set to 90.5% and the doc now carries the number so
the next drift is visible.

The largest single gap was pkg/security/tools/cosigntest at 0%: Go
attributes coverage per test binary and that package is a harness consumed
only by other packages' tests. Excluding it would have cleared the number
and been wrong -- it generates a /bin/sh script whose quoting,
cross-process counter and stream selection three retry suites silently
depend on, so a break there turns those suites green for the wrong reason.
It gets tests instead, driven through tools.ExecCommand (the function
signing.RunCosignWithRetry actually calls) so stdout and stderr stay
separated the way they do in production.

Also fixes two staticcheck SA1012 findings (never pass a nil Context) that
surface on this branch but not on main, in the cases asserting
lookupTriggeringEvents short-circuits before any AWS call -- they now pass
an already-cancelled context, so a regression fails with context.Canceled
instead of reaching the network.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
Cre-eD added a commit that referenced this pull request Aug 21, 2026
…old bar it claimed

OpenSSF Scorecard's Vulnerabilities check reported three advisories. All
three land on dev-tool-only modules pulled in through tools.go, and all
three are fixable upstream, so they are fixed rather than VEX'd:

  golang.org/x/mod      v0.38.0 -> v0.40.0   GO-2026-6179, GO-2026-6180 (HIGH)
  github.com/cilium/ebpf v0.11.0 -> v0.22.0  GO-2026-6238 (LOW)

Neither could be fixed by bumping its parent: gofumpt v0.11.0 (latest)
still requires x/mod v0.38.0, and delve v1.27.1 (latest) still requires
ebpf v0.11.0. `go list -deps ./...` links zero packages from either
module into anything we ship, but a non-breaking upstream fix exists, and
VEX is for findings that cannot be fixed.

osv-scanner and trivy fs both go from 3 findings to 0.

The ebpf bump has fallout worth calling out. ebpf v0.22.0 names
honnef.co/go/tools v0.7.0 in its own go.mod, MVS raises it, and
golangci-lint v1.64.8 does not compile against v0.7.0's analysis API --
it panics mid-run ("typedness: panic during analysis: interface
conversion: interface {} is nil, not *buildir.IR") and exits 7, failing
the lint step in branch.yaml / push.yaml. ebpf needs staticcheck for ITS
CI, not for anything we compile, and a require line loses to ebpf's, so
honnef is pinned back with a replace directive. Dependabot #385 makes the
same ebpf bump and would have broken lint on main on its own.

Images, all four rebuilt with --no-cache and rescanned:

  caddy           11 HIGH + 1 MEDIUM -> 1 MEDIUM
  cloud-helpers   8 HIGH             -> 0
  github-actions  17 HIGH            -> unchanged (Google's gcloud binaries)
  kubectl         14 HIGH + 3 MEDIUM -> unchanged (upstream kubectl binary)

caddy: the pinned 2.11.4-builder digest shipped Go 1.26.5 and the tag has
since been rebuilt with Go 1.26.7. Since xcaddy in the builder stage
produces the binary COPY --from=builder puts into the runtime image, the
builder's toolchain IS the shipped stdlib -- refreshing the digest alone
closed 8 stdlib CVEs. Three xcaddy --replace directives lift Caddy's own
vendored x/net, x/text and grpc past CVE-2026-46600, CVE-2026-56852 and
GHSA-hrxh-6v49-42gf. --replace and not --with, because --with also writes
a blank import and none of those modules has a package at its root.

cloud-helpers: every finding was in /usr/local/bin/aws-lambda-rie, the
base image's local-testing Runtime Interface Emulator. /lambda-entrypoint.sh
execs it only when AWS_LAMBDA_RUNTIME_API is unset, and our ENTRYPOINT
replaces that script outright, so it never runs -- and the debug path that
does use a RIE (welder run debug-aws-cloud-helpers) is runOn: host and uses
the host's copy. Deleting it is the fix, not a suppression. Image now
scans clean and the binary still starts.

Deferred: cel-go 0.28.1 -> 0.29.0 (MEDIUM, GHSA-gcjh-h69q-9w9g) inside
the caddy binary. v0.29.0 renames interpreter.Interpretable to
InterpretableV2 and Caddy 2.11.4's celmatcher.go does not compile against
it -- an upstream code change. Reachability and the closing condition are
recorded in a caddy.Dockerfile comment so the next digest refresh does not
silently add it to the --replace list and break the build.

Documented unfixable, each measured rather than assumed: kubectl's own
binary (pinned digest and current latest are both v1.36.3 with identical
findings, so the pin is left alone), the gcloud SDK binaries (579.0.0 and
581.0.0 both ship gcloud-crc32c built with go1.26.5, so bumping the pin
buys nothing), and the lambda base digest, which is deliberately NOT
refreshed because the currently-tagged one is worse (30 HIGH vs 8).

VEX: all three statements re-triaged against the current tree with fresh
evidence, none flipped, document bumped to version 4. No new suppression
was added anywhere -- no .trivyignore, no new VEX statement, no new
osv-scanner.toml entry.

Coverage: docs/TESTING.md claimed the Gold-tier test_statement_coverage90
criterion was Met. It was not -- the main baseline reads 89.6%. Seven test
files take the included set to 90.5% and the doc now carries the number so
the next drift is visible.

The largest single gap was pkg/security/tools/cosigntest at 0%: Go
attributes coverage per test binary and that package is a harness consumed
only by other packages' tests. Excluding it would have cleared the number
and been wrong -- it generates a /bin/sh script whose quoting,
cross-process counter and stream selection three retry suites silently
depend on, so a break there turns those suites green for the wrong reason.
It gets tests instead, driven through tools.ExecCommand (the function
signing.RunCosignWithRetry actually calls) so stdout and stderr stay
separated the way they do in production.

Also fixes two staticcheck SA1012 findings (never pass a nil Context) that
surface on this branch but not on main, in the cases asserting
lookupTriggeringEvents short-circuits before any AWS call -- they now pass
an already-cancelled context, so a regression fails with context.Canceled
instead of reaching the network.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
Cre-eD added a commit that referenced this pull request Aug 21, 2026
…e to 90.5 % (#387)

## Summary

Closes every fixable dependency vulnerability in the repo across all
severities, and lifts included-set statement coverage over the Gold-tier
bar it was documented as already meeting.

| | before | after |
|---|---|---|
| **OpenSSF Scorecard `Vulnerabilities`** | 3 advisories
(`GO-2026-6238`, `GO-2026-6179`, `GO-2026-6180`) | **0** |
| `osv-scanner` on `go.mod` | 3 (2 packages) | **0** |
| `trivy fs` | 2 HIGH + 1 LOW | **0** |
| Dependabot open alerts | 1 (LOW) | closes on merge |
| `simplecontainer/caddy` image | 11 HIGH + 1 MEDIUM | **1 MEDIUM** |
| `simplecontainer/cloud-helpers` image | 8 HIGH | **0** |
| `simplecontainer/github-actions` image | 17 HIGH | unchanged (upstream
binaries) |
| `simplecontainer/kubectl` image | 14 HIGH + 3 MEDIUM | unchanged
(upstream binary) |
| Included-set statement coverage | 89.6 % | **90.5 %** |

Deferred: 1 (cel-go, needs an upstream Caddy code change). Documented
unfixable: 4 classes, all upstream-owned binaries.

The Scorecard `Vulnerabilities` check was the trigger, and all three
advisories it reported land on **dev-tool-only** dependencies (`delve`
and `gofumpt` via `tools.go`) — `go list -deps ./...` links **zero**
packages from either module into anything we ship. They are still fixed
rather than VEX'd, because a fix exists upstream and is non-breaking;
VEX is for findings that cannot be fixed.

## Fixed

### Go modules

| Package | Old → New | Advisory | Sev | Reported by |
|---|---|---|---|---|
| `golang.org/x/mod` | v0.38.0 → **v0.40.0** | `GO-2026-6179` /
`CVE-2026-56865` — tlog tile verification bypass | HIGH | Scorecard,
osv-scanner, trivy fs |
| `golang.org/x/mod` | v0.38.0 → **v0.40.0** | `GO-2026-6180` /
`CVE-2026-56864` — unauthenticated hashes honoured in `sumdb.Lookup` |
HIGH | Scorecard, osv-scanner, trivy fs |
| `github.com/cilium/ebpf` | v0.11.0 → **v0.22.0** | `GO-2026-6238` /
`CVE-2026-10722` / `GHSA-xhgw-qwwf-pg32` — integer overflow in BTF
parsing | LOW | Scorecard, osv-scanner, trivy fs, Dependabot |

Neither could be fixed by bumping its parent: `mvdan.cc/gofumpt` v0.11.0
(latest) still requires `x/mod` v0.38.0, and `go-delve/delve` v1.27.1
(latest) still requires `cilium/ebpf` v0.11.0. Both are therefore raised
by an explicit indirect requirement.

MVS collateral, no advisory of its own, listed for review completeness:

`golang.org/x/crypto` v0.54.0 → v0.55.0 · `golang.org/x/net` v0.57.0 →
v0.58.0 · `golang.org/x/text` v0.40.0 → v0.41.0 · `golang.org/x/tools`
v0.48.0 → v0.49.0 · `golang.org/x/exp/typeparams` ·
`golang.org/x/telemetry` · `github.com/sirupsen/logrus` v1.9.3 → v1.9.4

### `caddy.Dockerfile` — 11 HIGH closed

Two independent causes, both fixed:

1. **Builder digest refresh** `198d47e` → `4bdeabce` (same
`2.11.4-builder` tag, rebuilt 2026-08-20). The pinned digest carried
**Go 1.26.5**; the current one carries **Go 1.26.7**. Since `xcaddy
build` in the builder stage produces the binary that `COPY
--from=builder` puts into the runtime image, the builder's toolchain
*is* the shipped binary's stdlib — this alone closed 8 stdlib CVEs
(`CVE-2026-33818`, `-39821`, `-46600`, `-56853`, `-56858`, `-56859`,
`-56860`, `-56862`). Runtime digest refreshed alongside it (`844f60b6` →
`df7f1c2f`) so builder and runtime stay on the same tag push.
2. **Three `xcaddy --replace` directives** lifting Caddy 2.11.4's own
vendored deps past `CVE-2026-46600` (`x/net` → v0.58.0),
`CVE-2026-56852` (`x/text` → v0.41.0) and `GHSA-hrxh-6v49-42gf` (`grpc`
→ v1.82.1). `--replace` and not `--with`: `--with` also writes a blank
import, and none of these modules has a package at its module root, so
it fails with `cannot find module providing package`.

The Dockerfile's existing build-time gates (`caddy version | grep`,
`caddy list-modules | grep` for `rate_limit` and `storage.gcs`) all
still pass, so a silently dropped plugin or a version skew would have
failed the build.

### `cloud-helpers.aws.Dockerfile` — 8 HIGH closed, image now clean

Every finding in this image came from `/usr/local/bin/aws-lambda-rie`,
the base image's **local-testing** Runtime Interface Emulator: 9 MB of
Go that AWS builds with an older toolchain (Go 1.26.5 at the pinned
digest → 8 HIGH, all fixed in Go ≥ 1.26.6).

It is not reachable in this image. `/lambda-entrypoint.sh` execs it only
when `AWS_LAMBDA_RUNTIME_API` is unset, and our `ENTRYPOINT
["/cloud-helpers"]` replaces that script outright. Nothing links it and
no workflow invokes it — `welder run debug-aws-cloud-helpers` is `runOn:
host` and uses the **host's** `aws-lambda-rie`, not the image's copy. So
it is deleted, which is a fix rather than a suppression.

What this removes is `docker run --entrypoint /lambda-entrypoint.sh
<image> /cloud-helpers`; the welder task is the supported path. Verified
after the change: the image scans clean **and** `/cloud-helpers` still
starts (it exits with the expected "did you pass
SIMPLE_CONTAINER_CLOUD_HELPER_TYPE" error).

### `honnef.co/go/tools` pinned to v0.6.1 via `replace`

`cilium/ebpf` v0.22.0 names `honnef.co/go/tools` v0.7.0 in its own
`go.mod`, so MVS raises it. `golangci-lint` v1.64.8 does not compile
against v0.7.0's analysis API and **panics mid-run**, exit 7:

```
typedness: panic during analysis: interface conversion: interface {} is nil, not *buildir.IR
  honnef.co/go/tools@v0.7.0/analysis/facts/typedness/typedness.go:59
```

That fails the `golangci-lint run` step in `branch.yaml` / `push.yaml` /
`branch-preview.yaml`. ebpf needs staticcheck for *its* CI, not for any
code we compile, and v0.22.0 is the fix for `GO-2026-6238` so it cannot
be held back — and a `require` line loses to ebpf's, so only `replace`
pins it. `honnef.co/go/tools` v0.6.1 carries no advisories (checked
against osv.dev). Removal condition is in the go.mod comment:
golangci-lint v2 builds against v0.7.x, but that is a separate migration
(module path rename + `.golangci.yml` schema change).

**This is the reason to supersede Dependabot #385 rather than merge it**
— #385 makes exactly this bump and would have broken lint on `main` on
its own.

## Deferred (breaking change, needs upstream)

**`GHSA-gcjh-h69q-9w9g` — `github.com/google/cel-go` v0.28.1 → v0.29.0,
MEDIUM, inside the shipped `caddy` binary.**

Not a version bump: v0.29.0 renames `interpreter.Interpretable` to
`InterpretableV2`, and Caddy 2.11.4's `modules/caddyhttp/celmatcher.go`
does not compile against it. Verified by attempting it:

```
caddy/v2@v2.11.4/modules/caddyhttp/celmatcher.go:506:5: cannot use []interpreter.Interpretable{…}
  (value of type []interpreter.Interpretable) as []interpreter.InterpretableV2 value in argument to interpreter.NewCall
caddy/v2@v2.11.4/modules/caddyhttp/celmatcher.go:529:5: (same)
```

**Reachability**: cel-go backs Caddy's `expression` request matcher.
SC's generated Caddyfiles never emit `expression` (0 occurrences across
the Caddyfile templates in `pkg/clouds/pulumi/kubernetes/`), so the CEL
evaluator is only reachable if a consumer writes one by hand into
`lbConfig.extraHelpers` / `siteExtraHelpers`. **Closing condition**: a
Caddy release that adopts cel-go ≥ 0.29.0 — then drop this note and
rebuild. Deliberately called out in a `caddy.Dockerfile` comment so the
next digest refresh does not silently add it to the `--replace` list and
break the build.

## Documented unfixable (upstream-owned binaries, no action available)

1. **`alpine/kubectl` → `/usr/local/bin/kubectl`** — 8 HIGH
`stdlib@v1.26.5`, 5 HIGH + 3 MEDIUM `x/net@v0.49.0`, 1 HIGH
`x/text@v0.33.0`. kubectl is built by the Kubernetes release process; we
cannot rebuild it. Refreshing the digest gains nothing and was measured,
not assumed: the pinned digest `5d380d18` and the current `latest`
(`dae26110`, = tag `1.36.3`) are **both kubectl v1.36.3** and produce
**identical** finding counts, so the pin is left alone rather than
churned. The Dockerfile's `apk upgrade` already clears **all**
OS-package findings (0 alpine findings on a fresh build). Closing
condition: a Kubernetes patch release rebuilt with Go ≥ 1.26.6, then
refresh the digest.
2. **Google Cloud SDK binaries in `github-actions`** — 8 HIGH in
`gcloud-crc32c` (`stdlib@v1.26.5`) and 9 HIGH in
`gke-gcloud-auth-plugin` (8 × `stdlib@v1.26.5` + `x/text@v0.38.0` /
`CVE-2026-56852`). That is the image's *entire* finding set: base OS
packages scan 0 and `root/github-actions` scans 0.
`gke-gcloud-auth-plugin` is fetched by `gcloud components install` at
build time, so it is already the freshest version Google publishes.
Bumping the pin does **not** help, also measured rather than assumed:
`GCLOUD_VERSION` 579.0.0 (pinned) and 581.0.0 (latest) both ship
`gcloud-crc32c` built with **go1.26.5** (`go version` on the extracted
binaries). The pin stays at 579.0.0 and its `GCLOUD_SHA256` was
re-verified correct against a fresh download. *Reachability*:
`gcloud-crc32c` is a checksum helper for `gcloud storage` / gsutil
transfers, and no SC code path shells out to either (0 matches for
`gsutil` across `pkg/`; GCP static-site uploads go through the Pulumi
SDK's `storage.BucketObject`). Not deleted the way the Lambda RIE was,
because a consumer-authored deploy hook *can* invoke `gcloud storage`,
so the execute path is not provably empty. Candidate for an image-scope
VEX statement once this repo has a convention for one — today
`vex/openvex.json` covers Go-module advisories only.
3. **`public.ecr.aws/lambda/provided:al2023` digest is deliberately NOT
refreshed.** The currently-tagged digest is **worse** than the pinned
one: 30 HIGH vs 8. Anyone rebasing a Dependabot docker-digest bump onto
this image should check the scan before taking it.
4. **`GO-2026-5932`** (`golang.org/x/crypto/openpgp` unmaintained) —
unchanged `not_affected`, re-triaged below.

## VEX re-triage

All three statements in `vex/openvex.json` re-checked against the
current tree this pass; document bumped to `version: 4`, `timestamp:
2026-08-21`. No statement flipped, and each was **re-confirmed with
fresh evidence** rather than carried forward by default:

| Advisory | Status | This pass |
|---|---|---|
| `GO-2022-0635` (aws-sdk-go v1 s3crypto) | `not_affected` /
`component_not_present` | **Re-confirmed.** Still 0 matches in `go.mod`
and `go.sum`; `go mod why -m` still reports "main module does not need";
`go list -m all` still resolves v1.55.8 only through a transitive
`go.mod`. |
| `GO-2022-0646` (same module) | `not_affected` /
`component_not_present` | **Re-confirmed**, same evidence. |
| `GO-2026-5932` (x/crypto/openpgp) | `not_affected` /
`vulnerable_code_not_present` | **Re-confirmed.** `go list
-buildvcs=false -deps ./...` still links 24 `x/crypto` packages and
**0** `openpgp` packages; OpenPGP still goes through
`ProtonMail/go-crypto`; no fix event upstream (`introduced: 0`,
permanent "unmaintained" notice). Impact statement updated for the
`x/crypto` v0.54.0 → v0.55.0 bump in this PR. |

`osv-scanner.toml` needs no change: its single mirrored entry
(`GO-2026-5932`) is still the only one of the three that osv-scanner
actually reports, and it still filters correctly (`Filtered 1
vulnerability from output`). No new suppressions were added anywhere —
no `.trivyignore`, no new VEX statement, no new `IgnoredVulns` entry.

## Coverage: 89.6 % → 90.5 %

`docs/TESTING.md` claimed the Gold-tier `test_statement_coverage90`
criterion was **Met**. It was not: the `main` baseline artifact reads
`included=89.6`, reproduced exactly locally. This PR closes the gap and
makes the doc honest — the status column now carries the number, so the
next drift is visible.

The included set is 5,975 statements, so 90 % needed 29 more covered
statements. Seven test files add ~60, all of them exercising real logic
with assertions that fail on a real regression rather than padding the
denominator:

| Test | What it guards |
|---|---|
| `pkg/security/tools/cosigntest/cosigntest_test.go` **(new, 208
lines)** | The whole package was at **0 %** — see below. |
| `pkg/clouds/gcloud/auth_test.go` | `ReadSecretsProviderConfig` must
reject a bad `keyRotationPeriod` **at read time** (4 shapes), and must
ignore it when `provision: false`. This is the contract the function's
own comment describes: an already-provisioned secrets-provider stack is
skipped by the provisioner, so a provisioner-only check never runs and a
bad value would surface at a DR rebuild. Plus
`EffectiveNoncurrentVersionRetentionDays` — nil means "apply the 30-day
default", explicit zero means "disable the rule"; collapsing the two
would silently drop the rollback horizon on every state bucket that
never set the field. |
| `pkg/clouds/compose/compose_test.go` | An absolute `composeFilePath`
must re-root `workingDir` onto the file's own directory (relative build
contexts resolve against `workingDir`, so honouring the caller's would
point them at the wrong tree); `${VAR}` interpolation must still read
the process env under `SkipResolveEnvironment`; a missing file must not
return a half-built project. |
| `pkg/clouds/fs/fs_state_test.go` | `init()`'s two registrations,
asserted **through `api.ReadProvisionerFieldConfig`** — the same lookup
the descriptor reader uses. A typo'd key or a reader wired to the wrong
struct otherwise only shows up as `unknown provisioner field config
type` at read time. |
| `pkg/clouds/docker/types_test.go` | `RegistryRequiresAuth` gates
whether an imagePullSecret is generated at all:
username-without-password must read as "no auth" rather than produce a
half-formed secret, while both-present-but-empty must still count as
"auth requested" so the deploy fails on a bad credential instead of
silently pulling anonymously. |
| `pkg/clouds/cloudflare/cloudflare_test.go` | `ReadRegistrarConfig`
happy + error path, including that `dnsRecords` survives the yaml
round-trip `ConvertConfig` performs. |
| `pkg/clouds/mongodb/mongodb_test.go` | `ReadAtlasConfig` happy + error
path, with the `*float64` / `*int` fields asserted specifically: they
distinguish "unset" from "explicitly zero" and must survive the
round-trip, and unset ones must stay nil so downstream defaults apply. |

### Why `cosigntest` got tests instead of an exclusion

`pkg/security/tools/cosigntest` was the single largest uncovered block
in the included set (42 statements, 0 %) because Go attributes coverage
per test binary, and this package is a harness consumed only by *other*
packages' tests (`pkg/security/provenance`, `pkg/security/sbom`).

Adding it to the `pkg/util/test/*` exclusion category would have been
the cheap way to clear the number, and it would have been wrong. The 0 %
is a real gap: the package generates a `/bin/sh` script, and three retry
suites silently depend on its shell quoting, its cross-process
invocation counter, and which stream it writes the Rekor conflict marker
to. A break there turns those suites green for the wrong reason. So the
new tests drive the stub through **`tools.ExecCommand`** — the exact
function `signing.RunCosignWithRetry` calls — so stdout and stderr stay
separated the way they do in production, and they include:

- the `ConflictOnStdout` case asserting stderr is **non-empty but does
not contain the marker**, so a stdout-classification bug cannot pass
because the marker leaked onto both streams;
- a `FailStderr` body containing a single quote — the exact input that
broke an earlier harness by terminating the generated script early;
- `shellQuote` round-tripped through `/bin/sh` itself, including a
metacharacter payload, because string equality alone would not catch a
quoting form the shell re-splits or expands;
- `DelayEach` vs `DelayFirst` asserted per invocation, which is what
distinguishes a fresh per-attempt timeout from one budget shared across
attempts;
- `RekorConflictStderr` checked against the `[POST
/api/v1/log/entries][409]` shape the retry classifier actually anchors
on, so a drifted fixture cannot quietly stop exercising the retry path.

`docs/TESTING.md` records why it is *not* excluded, next to the
exclusion table.

## Also in this PR

`pkg/clouds/aws/helpers/ct_enrichment_test.go` — two `staticcheck`
`SA1012` findings (never pass a nil `Context`) that surface on this
branch but not on `main`. Fixed properly rather than silenced: the cases
assert that `lookupTriggeringEvents` short-circuits **before** any AWS
call, so they now pass an already-cancelled context instead of `nil` — a
regression that stops short-circuiting fails with `context.Canceled`
instead of reaching the network.

**Pre-existing lint drift, deliberately left alone:** `golangci-lint run
--fix` (the exact CI invocation) rewrites 19 unrelated files on `main`
today — `gci` import ordering plus missing `goheader` SPDX headers in
`pkg/api/secrets/ciphers/x25519.go`, `x25519_test.go` and
`pkg/clouds/pulumi/aws/permissions_boundary.go`. CI is green because
`--fix` repairs them in the workspace and never commits them. Worth a
separate cleanup PR; folding 19 files of import churn into an SCA diff
would only make this one harder to review.

## Dependabot reconciliation

| PR | Action |
|---|---|
| **#385** `bump github.com/cilium/ebpf 0.11.0 → 0.22.0` | **Superseded
— close.** Same bump, plus the honnef/golangci-lint fallout it would
have hit alone (see above). |
| **#382** `bump caddy from 198d47e to c7ae802` | **Close or rebase.**
Already stale: the `caddy` tags were rebuilt 2026-08-20 and this PR pins
the resulting digests directly (`4bdeabce` builder / `df7f1c2f`
runtime), so #382 conflicts and targets an older push. |
| #380 `github-actions group`, #381 `reecetech/version-increment`, #378
`node 22-alpine → 26-alpine` | Left open. Separate docker / actions
version stream per `.github/dependabot.yml`; no overlap with this diff.
|

Open Dependabot **alerts**: 1 (`github.com/cilium/ebpf`, LOW, fix
0.22.0). Closes automatically once this lands on `main`. The two `x/mod`
advisories never opened an alert — Dependabot did not surface them —
which is precisely why the Scorecard / osv-scanner / trivy cross-check
matters and why alert state alone is not the source of truth.

`.github/dependabot.yml` needs no change: both language ecosystems
(`gomod` at `/`, `pip` at `/docs`) and both version ecosystems
(`docker`, `github-actions`) are already configured.

## Evidence

<details>
<summary>Source scans, before → after</summary>

```
# osv-scanner scan source --lockfile=go.mod     (the scanner OpenSSF Scorecard uses)
BEFORE  github.com/cilium/ebpf@0.11.0   GO-2026-6238, GHSA-xhgw-qwwf-pg32
        golang.org/x/mod@0.38.0         GO-2026-6179, GO-2026-6180
        (+ GO-2026-5932 filtered by osv-scanner.toml)
AFTER   CLEAN
        (+ GO-2026-5932 filtered by osv-scanner.toml — still the only mirrored entry)

# trivy fs --severity CRITICAL,HIGH,MEDIUM,LOW
BEFORE  HIGH  golang.org/x/mod@v0.38.0      CVE-2026-56864   fix=0.40.0
        HIGH  golang.org/x/mod@v0.38.0      CVE-2026-56865   fix=0.40.0
        LOW   github.com/cilium/ebpf@v0.11.0 CVE-2026-10722  fix=0.22.0
AFTER   CLEAN   (0 findings; docs/requirements.txt also 0)

# reachability of the two fixed modules — neither links into anything we ship
go list -buildvcs=false -deps ./... | grep -c '^golang.org/x/mod'        -> 0
go list -buildvcs=false -deps ./... | grep -c '^github.com/cilium/ebpf'  -> 0
```
</details>

<details>
<summary>Image scans — built locally from this branch vs from
origin/main</summary>

Both sides built from the same Dockerfiles at the same moment, so this
is apples to apples rather than a comparison against the published
`:latest` tags (which lag the current Dockerfiles and are much worse —
caddy 178 findings, cloud-helpers 72, github-actions 151, kubectl 92;
the next release build closes that gap regardless).

All four images rebuilt with `docker build --no-cache`. That matters: a
first pass reported 48 phantom `python3` findings in `github-actions`
because BuildKit reused a cached `apk update && apk upgrade && apk add`
layer (the layers came into the local store from pulling the published
image for the "before" scan), so the image kept `python3 3.14.5-r0`
while `alpine v3.24/main` already served `3.14.7-r1`. Fresh builds — and
CI runners — install the current package. Worth knowing before trusting
any local image scan in this repo.

```
caddy — docker build -f caddy.Dockerfile
  origin/main   HIGH=11 MEDIUM=1
                x/net@v0.55.0     CVE-2026-46600
                x/text@v0.37.0    CVE-2026-56852
                grpc@v1.81.0      GHSA-hrxh-6v49-42gf
                stdlib@v1.26.5    CVE-2026-33818 -39821 -46600 -56853 -56858 -56859 -56860 -56862
                cel-go@v0.28.1    GHSA-gcjh-h69q-9w9g  (MEDIUM)
  this branch   MEDIUM=1
                cel-go@v0.28.1    GHSA-gcjh-h69q-9w9g  <- deferred, upstream-breaking
  gates:        caddy version -> v2.11.4 ; http.handlers.rate_limit + caddy.storage.gcs present
  OS packages:  0 both sides (apk upgrade already handled it)

cloud-helpers — docker build -f cloud-helpers.aws.Dockerfile
  origin/main   HIGH=8      all in usr/local/bin/aws-lambda-rie (stdlib@v1.26.5)
  this branch   0 findings  amazon OS 0 ; /cloud-helpers 0 ; RIE removed
  smoke:        /cloud-helpers starts (exits on missing SIMPLE_CONTAINER_CLOUD_HELPER_TYPE)

kubectl — docker build -f kubectl.Dockerfile
  this branch   HIGH=14 MEDIUM=3   all in usr/local/bin/kubectl (upstream)
                alpine OS packages: 0
  digest check  pinned 5d380d18 and latest dae26110 are both kubectl v1.36.3,
                identical finding counts -> pin left alone

github-actions — docker build -f github-actions.Dockerfile
  this branch   HIGH=17     alpine OS 0 ; root/github-actions 0
                gcloud-crc32c            8 HIGH  stdlib@v1.26.5      (upstream)
                gke-gcloud-auth-plugin   9 HIGH  stdlib@v1.26.5 + x/text@v0.38.0  (upstream)
  unchanged vs origin/main — neither the alpine base nor the gcloud pin moved,
  and our binary scans 0 on both sides.
  smoke:        pulumi version / gcloud version / gke-auth-plugin present /
                aws --version / sc symlink all pass in-build

our own Go binaries, scanned directly (trivy rootfs + grype --only-fixed)
  dist/github-actions   go1.26.6   trivy 0 / grype 0
  dist/cloud-helpers    go1.26.6   trivy 0 (in-image scan)
```
</details>

<details>
<summary>Coverage</summary>

```
# main baseline (coverage.yml artifact, run 32352899068, sha ec0f628)
included=89.6
full=28.9

# this branch, same filter as coverage.yml / welder.yaml
included: 90.5%
full:     29.0%

# gap arithmetic
included set = 5,975 statements ; 5,348 covered = 89.506%
90.0% needed +29 covered statements ; this PR adds ~60
```
</details>

## Test plan

- `go build ./...` — passes (locally with `-p 2`; the `pulumi-gcp` /
`pulumi-aws` SDK packages want several GB per compile process, so full
parallelism OOMs on a 19 GB machine).
- `go test ./...` — passes except one pre-existing, environment-only
failure:
`TestDetectRootDir/WithDetectRootDir_errors_when_no_git_repo_is_found_above_cwd`.
It asserts that `WithDetectRootDir()` errors when no git repo exists
above `cwd`, and this machine has a `.git` above every temp dir
(`/home/creed/.git`, plus a stray `/tmp/.git` from an unrelated
worktree). Untouched by this PR — no file under `pkg/api/git/` is in the
diff — and CI runners have neither, so `Run tests` should be green.
- `golangci-lint run --fix --timeout 20m` (the CI invocation) — **exit
0**.
- `bin/gofumpt -l` — clean on every file in this diff.
- `go build` of all five `tools.go` targets against the bumped deps —
`dlv` (the risky one: `cilium/ebpf` v0.11.0 → v0.22.0 is a 11-minor jump
and delve pins the old one), `gofumpt`, `golangci-lint`, `mockery`,
`go-jsonschema` — all build.
- `docker build` of `caddy.Dockerfile`, `cloud-helpers.aws.Dockerfile`,
`kubectl.Dockerfile`, `github-actions.Dockerfile` — all succeed, with
the in-Dockerfile smoke tests (`caddy version`, plugin greps, `pulumi
version`, `gcloud version`, gke-auth-plugin presence, `aws --version`,
`sc` symlink) passing.
- `govulncheck -mode=source ./...` — **not run locally**: it peaks
around 13.5 GB RSS on this module. The `govulncheck` workflow gates this
PR and scans unconditionally on a Go-touching diff, which this is.

## CI on this PR

All checks green: `Build Setup (clean, tools, schemas, lint, fmt)`, `Run
tests`, `govulncheck (reachability-aware)`, `Analyze Go (go)` / CodeQL,
`security / SBOM + Dependency Scan`, `security / Secret Scan`,
`semgrep`, `Measure statement coverage`, all five `Build *` jobs, and
`Fuzz HMAC cache parse path`.

Two notes for anyone reading the run history:

- `TestDetectRootDir` fails on my machine but passes in `Run tests`,
exactly as expected — the assertion needs a temp dir with **no** git
repo above it, and this laptop has one above every temp dir. Nothing
under `pkg/api/git/` is in the diff.
- `Fuzz HMAC cache parse path` failed on the first attempt and **passed
on re-run**. It was not a discovered crash: `FuzzCacheGetPath` reported
`context deadline exceeded` at exactly the 30.10 s `-fuzztime` boundary
and **no crash corpus was written** (`No files were found with the
provided path: pkg/security/testdata/fuzz/`), which is Go's fuzz
coordinator missing its shutdown grace period on a loaded runner.
Reproduced locally on this branch at 2.1 M execs — `PASS`, no corpus.
Nothing in `pkg/security` itself is in the diff; the only addition is a
test in the `pkg/security/tools/cosigntest` subpackage, which
`pkg/security` does not import.

The Scorecard `Vulnerabilities` check itself cannot run here —
`scorecard.yml` triggers on `push` to `main`, the weekly cron, and
`branch_protection_rule`, and the check queries osv.dev against the
default branch. It clears on the next `main` push after merge. The same
scanner (`osv-scanner scan source --lockfile=go.mod`, with
`osv-scanner.toml` applied) is what reports **0** in the evidence above.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file priority: high High priority security Security-advisory dependency fix — merge-first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant