chore(docker): bump alpine from 3.23 to 3.24 in the docker group across 1 directory - #333
Closed
dependabot[bot] wants to merge 1 commit into
Closed
chore(docker): bump alpine from 3.23 to 3.24 in the docker group across 1 directory#333dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
dependabot
Bot
requested review from
Cre-eD,
Laboratory,
smecsia and
universe-ops
as code owners
June 20, 2026 13:28
Semgrep Scan ResultsRepository:
Scanned at 2026-08-10 09:21 UTC |
Security Scan ResultsRepository:
Scanned at 2026-08-10 09:21 UTC |
Cre-eD
approved these changes
Jun 21, 2026
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
from
June 22, 2026 09:21
b56698a to
74e791c
Compare
📊 Statement coverageMeasured on the documented included set (see
Baseline: |
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
2 times, most recently
from
July 6, 2026 09:18
340869c to
472d125
Compare
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
from
July 20, 2026 09:20
472d125 to
84e7275
Compare
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
from
July 27, 2026 09:21
84e7275 to
242268f
Compare
6 tasks
Cre-eD
added a commit
that referenced
this pull request
Aug 3, 2026
…lities 8 → 10) (#372) ## Summary OpenSSF Scorecard's **Vulnerabilities** check is at **8/10** with 8 open advisories. This PR takes it to **10/10**. - **7 fixed by version bump** — 3 Go, 4 Python (all severities, nothing deferred). - **1 unfixable by design** — `GO-2026-5932` has `introduced: 0` and no fix event in OSV. Declared `not_affected` with reachability evidence. - **2 stale suppressions retired** — `GO-2022-0635` / `GO-2022-0646` no longer apply; removed rather than carried forward. `osv-scanner scan source -r .` → **No issues found** (was 8). Scorecard runs the same scanner (`osvscanner.DoScan` via `clients/osv.go`) against the repo root, so the check flips on merge to `main`. ## Fixed | Package | Old → New | Advisory | Sev | Where | |---|---|---|---|---| | `github.com/klauspost/compress` | 1.18.4 → 1.18.7 | GO-2026-5841 / GHSA-259r-337f-4rfw — OOB read in `s2` | HIGH | `go.mod` (indirect) | | `google.golang.org/grpc` | 1.81.1 → 1.82.1 | GO-2026-6061 / GHSA-hrxh-6v49-42gf — xDS RBAC + HTTP/2 server | HIGH | `go.mod` (indirect) | | `click` | 8.1.8 → 8.4.2 | PYSEC-2026-2132 / CVE-2026-7246 | MEDIUM | `docs/requirements.txt` | | `pymdown-extensions` | 10.21.3 → 11.0.1 | GHSA-9xwg-3r6f-jcx2 / CVE-2026-61632 — `b64` path traversal | MEDIUM | `docs/requirements.txt` | | `setuptools` | 82.0.1 → 83.0.0 | PYSEC-2026-3447 / CVE-2026-59890 | MEDIUM | `docs/requirements.txt` | | `soupsieve` | 2.8.3 → 2.9.1 | PYSEC-2026-3071 / CVE-2026-49476 — memory exhaustion | HIGH | `docs/requirements.txt` | | `soupsieve` | 2.8.3 → 2.9.1 | PYSEC-2026-3072 / CVE-2026-49477 — ReDoS in selector parser | HIGH | `docs/requirements.txt` | Side-effect bumps pulled in by the above: `x/crypto` 0.53.0 → 0.54.0, `x/sys` 0.46.0 → 0.47.0, `x/term` 0.44.0 → 0.45.0, `opentelemetry-operations-go/detectors/gcp` 1.31.0 → 1.32.0, `contrib/detectors/gcp` 1.42.0 → 1.43.0, plus the `tools.go` chain (see *CI ordering* below). ### How the Python side was done `docs/requirements.in` gains explicit patched floors for the four packages, following the pattern already established for `requests` / `urllib3` after #264 — pinning the floor in the `.in` file is what stops a future `pip-compile` from silently resolving back to a vulnerable version. `docs/requirements.txt` was then regenerated with `pip-compile --allow-unsafe --generate-hashes --upgrade`. `mkdocs-material` 9.7.7 declares `pymdown-extensions>=10.2` with no upper bound, so the 11.x major is in range for the theme — no theme pin change needed, and the docs site builds clean (evidence below). The `b64` extension that carries CVE-2026-61632 is not enabled in `docs/mkdocs.yml` at all; the bump closes the advisory rather than a live exposure. ## Not fixable — `GO-2026-5932` (`golang.org/x/crypto/openpgp`) > The `golang.org/x/crypto/openpgp` package is unmaintained, unsafe by design, and has known security issues. This is a permanent "this package should not be used" notice, not a patchable defect. In OSV it is `introduced: 0` with **no fix event**, so no version of `x/crypto` clears it — bumping to 0.54.0 (done here anyway, for hygiene) changes nothing. **Reachability:** 1. **Where in the tree** — `x/crypto` is a direct dependency, required for `chacha20poly1305` in `pkg/api/secrets/ciphers`. The advisory covers only `openpgp` and its six subpackages. 2. **Is it in the artifact** — no. `go list -deps ./... | grep x/crypto/openpgp` returns nothing, and Go's linker does not emit packages no import path reaches. The vulnerable code is not present in any binary this repo produces. 3. **Is the vulnerable code called** — no. `govulncheck -mode=source ./...` reports **0 reachable vulnerabilities**; this advisory lands in its "modules you require, but your code doesn't appear to call" bucket. 4. **What OpenPGP work actually runs** — `github.com/ProtonMail/go-crypto/openpgp`, which is the maintained fork the advisory text itself recommends as the replacement. 5. **What would change the answer** — any new import of `x/crypto/openpgp/*`. That would flip the VEX statement to `affected` and block the gate. Recorded as `status: not_affected`, `justification: vulnerable_code_not_present` in [`vex/openvex.json`](vex/openvex.json), mirrored into [`osv-scanner.toml`](osv-scanner.toml) — Scorecard's check has no VEX input, so the mirror is the only channel that reaches it. No `.trivyignore`, no `# nosec`, nothing hidden. ## Re-triage of existing suppressions Both entries that predate this PR were re-checked rather than carried forward: | Advisory | Was | Now | Why | |---|---|---|---| | GO-2022-0635 (aws-sdk-go v1 s3crypto) | `not_affected` + ignore | `fixed`, ignore removed | `github.com/aws/aws-sdk-go` (v1) is no longer in `go.mod` — the Pulumi upgrades dropped the last build-graph edge and Go module pruning removed it. `osv-scanner` reported the entry as an **unused ignore**. | | GO-2022-0646 (same subpackage) | `not_affected` + ignore | `fixed`, ignore removed | Same. | VEX statements are kept one release as an audit trail; the `osv-scanner.toml` entries are gone. ## Governance changes - **CODEOWNERS** — `/vex/` and `/osv-scanner.toml` are now named explicitly. A `not_affected` statement hides a real advisory from both the scanners and the Scorecard badge; that is the same class of change as touching a workflow, and it should not merge on a generic `*` match. - **`docs/DEPENDENCIES.md`** — documents (a) that `osv-scanner.toml` is a *derivative* mirror which may only carry an ID that already exists in VEX, and (b) that every SCA pass re-triages both files, with `unused ignores` as the removal signal. Previously the policy said suppressions live "never in a scanner-suppression file" while `osv-scanner.toml` existed; policy and practice now agree. - **`osv-scanner.toml`** — added a note that `reason` must stay a single-line TOML basic string. A newline in it makes osv-scanner discard the **entire** config (`strings cannot contain newlines`) and silently re-report every ignored advisory. Hit while writing this PR. ## CI ordering (`tools.go` pre-bake) `build-setup` runs `go get $(tools.go imports)` → `go mod download` → `go generate -tags tools` → `go mod tidy`. Because `go get` resolves tools to *latest* and `tidy` only runs afterwards, a tool minor landing between runs breaks `go generate` with `missing go.sum entry`. The post-`go get` state is pre-baked into this commit so CI's `go get` is a no-op: `go-jsonschema` 0.23.1 → 0.24.1, `go-internal` 1.14.1 → 1.15.0, `gofumpt` 0.10.0 → 0.11.0, `x/mod` 0.37.0 → 0.38.0, `x/net` 0.56.0 → 0.57.0, `x/tools` 0.47.0 → 0.48.0, `x/telemetry` bumped. ## Dependabot reconciliation Open alerts before this PR: 5 — `pymdown-extensions`, `setuptools`, `soupsieve` ×2, `grpc`. All 5 are closed by the bumps above; they auto-resolve once this lands on `main`. `click` (PYSEC-2026-2132) and `klauspost/compress` (GO-2026-5841) were **not** alerted by Dependabot but are flagged by OSV — fixed here too. Open Dependabot PRs: | PR | Disposition | |---|---| | #361 `soupsieve 2.8.3 → 2.8.4` | Superseded — this PR goes to 2.9.1. Dependabot closes it automatically when the manifest lands. | | #371, #352, #351, #334, #333, #326 | Untouched — `github-actions` / `docker` streams, unrelated to this PR. | No config change needed: `.github/dependabot.yml` already covers `gomod` (/), `pip` (/docs), `docker`, and `github-actions`. ## Evidence <details> <summary><code>osv-scanner scan source -r .</code> — before</summary> ``` click 8.1.8 [PyPI] -> PYSEC-2026-2132 pymdown-extensions 10.21.3 [PyPI] -> GHSA-9xwg-3r6f-jcx2 setuptools 82.0.1 [PyPI] -> PYSEC-2026-3447, GHSA-h35f-9h28-mq5c soupsieve 2.8.3 [PyPI] -> PYSEC-2026-3071, PYSEC-2026-3072, GHSA-2wc2-fm75-p42x, GHSA-836r-79rf-4m37 klauspost/compress 1.18.4 [Go] -> GO-2026-5841 golang.org/x/crypto 0.53.0 [Go] -> GO-2026-5932 google.golang.org/grpc 1.81.1 [Go] -> GO-2026-6061, GHSA-hrxh-6v49-42gf osv-scanner.toml has unused ignores: - GO-2022-0635 - GO-2022-0646 ``` </details> <details> <summary><code>osv-scanner scan source -r .</code> — after</summary> ``` Scanned docs/requirements.txt file and found 36 packages Scanned go.mod file and found 486 packages Loaded filter from: osv-scanner.toml GO-2026-5932 has been filtered out because: VEX not_affected (vulnerable_code_not_present) ... Filtered 1 vulnerability from output No issues found ``` </details> <details> <summary><code>govulncheck -mode=source ./...</code> — after</summary> ``` === Symbol Results === No vulnerabilities found. Your code is affected by 0 vulnerabilities. This scan also found 0 vulnerabilities in packages you import and 1 vulnerability in modules you require, but your code doesn't appear to call these vulnerabilities. ``` The 1 module-level finding is GO-2026-5932, covered above. </details> ## Test plan - [x] `go build ./...` - [x] `go generate -tags tools` (post-pre-bake, matches CI's build-setup order) - [x] `go test ./pkg/api/secrets/... ./pkg/security/... -count=1` — all pass - [x] Docs built exactly as CI does it: `docker run --rm -v $PWD/docs:/docs -w /docs python@sha256:401f6e1a... sh -c "pip install --require-hashes -r requirements.txt && mkdocs build"` → `Documentation built in 3.39 seconds`, hash check clean, no new warnings - [x] `jq empty vex/openvex.json` - [ ] CI: govulncheck, CodeQL, Semgrep, build matrix Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
from
August 3, 2026 09:18
242268f to
41a5ed5
Compare
Bumps the docker group with 1 update in the / directory: alpine. Updates `alpine` from 3.23 to 3.24 --- updated-dependencies: - dependency-name: alpine dependency-version: '3.24' dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] <support@github.com>
dependabot
Bot
force-pushed
the
dependabot/docker/docker-2adcbce36e
branch
from
August 10, 2026 09:20
41a5ed5 to
e8da8bc
Compare
Contributor
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 |
Cre-eD
added a commit
that referenced
this pull request
Aug 11, 2026
…nd CI pins (#377) ## Summary Full SCA pass over source, all 5 published container images, and the CI pin surface. Consolidates the **7 open Dependabot PRs** into one review and adds 5 findings none of them could see. | | Fixed | Deferred | Documented unfixable | |---|---|---|---| | CRITICAL | 0 | 0 | 0 | | HIGH | 1 source + 102 image | 0 | 8 | | MEDIUM | 1 source + 32 image | 0 | 4 | | LOW | 0 + 1 image | 0 | 0 | Locally-built images, `origin/main` vs this branch, identical build inputs: | image | trivy (main → branch) | grype `--only-fixed` (main → branch) | |---|---|---| | `kubectl` | 21 → **8** | 39 → **11** | | `caddy` | 28 → **3** | 37 → **9** | | `cloud-helpers` | 64 → **0** | 27 → **4** | | `github-actions` | 34 → **1** | 44 → **5** | | **total** | **147 → 12** (−92%) | **147 → 29** (−80%) | Every one of the 12 remaining findings sits inside a third-party prebuilt binary already at its newest available version. Nothing fixable is left unfixed, and no suppression was added. > **Read Round 2 at the bottom too.** A six-model review panel plus two real preview builds followed this round; it corrected two defects in the diff below (cache scoping, and a weakened pin in `welder.yaml`) and found three pre-existing ones, including a Pulumi checksum gate that could not fail and a published image that cannot start. ## Fixed | Package | Old → New | CVE / advisory | Sev | Source | |---|---|---|---|---| | `github.com/go-git/go-git/v5` | 5.19.1 → 5.19.2 | CVE-2026-71556 (`GHSA-hc8v-wwc9-vgxm`) worktree ops follow symlinks | HIGH | trivy fs, osv-scanner, Dependabot alert #75 | | `github.com/go-git/go-git/v5` | 5.19.1 → 5.19.2 | CVE-2026-71557 (`GHSA-qgq7-7hm3-q39j`) malicious ref names write outside ref storage | MEDIUM | trivy fs, osv-scanner, Dependabot alert #76 | | Caddy binary (`xcaddy build`) | v2.11.3 → v2.11.4 | CVE-2026-52844, CVE-2026-52845 (HIGH), CVE-2026-52846 (MEDIUM) | H×2 M×1 | trivy image | | `alpine` base (×4 stages) | 3.23 → 3.24 | 30 distro CVEs → 0; also lifts `py3-cryptography` 46.0.7 → 47.0.0 | H2 M8 L20 | trivy image | | `caddy:2.11.4` + `-builder` | digest refresh | 55 → 25 in the base layer | H12 M23 L20 | trivy image | | `alpine/kubectl:latest` | digest refresh | 68 → 8 in the base layer | H20 M28 L20 | trivy image | | `lambda/provided:al2023` | digest refresh | 64 → 0 in the base layer | H58 M5 L1 | trivy image | | gcloud CLI | 567.0.0 → 579.0.0 | rolls up vendored Go deps in the bundled binaries; SHA-256 recomputed from the real tarball | — | trivy image | | `python:3.9.18` → `python@sha256:229a2c5b` (3.12-slim) (welder `build-docs`) | EOL runtime | 10110 → 213 image vulns (C248→4, H2293→23) | C/H/M/L | trivy image | ### CI pin bumps `actions/checkout` v6.0.3 → **v7.0.1** (Dependabot proposed v7.0.0; v7.0.1 adds the `--unset` escaping and default-input fixes) · `actions/cache` + `actions/cache/save` v5.0.5 → **v6.1.0** · `actions/setup-go` v6 → **v7.0.0** · `actions/attest-build-provenance` v4.1.0 → **v4.2.2** · `docker/setup-buildx-action` v4.1.0 → **v4.2.0** · `docker/build-push-action` v7.2.0 → **v7.3.0** · `ossf/scorecard-action` v2.4.3 → **v2.4.4** · `github/codeql-action` v4 SHA refresh (comment corrected to `# v4.37.6` in round 2). All SHAs resolved through the GitHub git-ref API, annotated tags dereferenced to commits. Compatibility checked before applying: - **ESM majors are safe here.** `checkout` v7, `cache` v6 and `setup-go` v7 are all "migrate to ESM" releases. Both the old and new versions declare `using: node24`, so no runner requirement changes on `blacksmith-8vcpu-ubuntu-2204`, `ubuntu-24.04` or `ubuntu-latest`. - **`checkout` v7's fork-PR block does not bite.** v7 refuses to check out fork PR code under `pull_request_target` / `workflow_run` unless `allow-unsafe-pr-checkout` is set. This repo has no `pull_request_target` at all; the three `workflow_run` workflows either do not check out (`security-scan-comment.yml`, `semgrep-comment.yml`) or check out the base repo with no `ref:` (`verify-attestations.yml`). The one PR-head checkout (`dco.yml`, `ref: github.event.pull_request.head.sha`) runs on `pull_request`, which the block does not cover. ### Stale pin comment `build-staging.yml` pinned `actions/cache@27d5ce7f` with a `# v4.3.0` comment, while `push.yaml` annotated the *same* SHA as `# v5.0.5`. The GitHub tag API confirms 27d5ce7f is **v5.0.5**; the v4.3.0 comment was wrong and made the pin look two majors older than it was. Corrected as part of the bump. ## Two findings Dependabot could not see ### 1. `caddy.Dockerfile` shipped a binary one patch behind its own base image The file header says *"Bumping requires editing all three '2.11.x' sites below (two FROMs + xcaddy)"*. Both `FROM` lines were on `caddy:2.11.4`, but `xcaddy build "v2.11.3"` was left behind, and the built binary is what `COPY --from=builder /usr/bin/caddy` puts in the final image. So the shipped Caddy was 2.11.3 and still carried CVE-2026-52844 + CVE-2026-52845. Dependabot tracks `FROM` lines, not `xcaddy` arguments, so this class of drift is invisible to it. Verified after the fix: ``` $ docker run --rm --entrypoint sh <built> -c 'cat /etc/alpine-release; caddy version; caddy list-modules | grep -E "rate_limit|gcs"' 3.23.5 v2.11.4 h1:XKxkMTgNSizEvKG6QHue6cAsFOteU2qA61w2tKkCWi0= caddy.storage.gcs http.handlers.rate_limit ``` ### 2. Published images do not match the Dockerfiles that supposedly built them `simplecontainer/caddy:latest` is byte-identical to `:2026.8.3` (both `sha256:83b0e6bb…`, pushed 2026-08-10 11:52 UTC, today). What is inside it: ``` $ docker run --rm --entrypoint sh simplecontainer/caddy:latest -c \ 'cat /etc/alpine-release; caddy version; ls -la /usr/bin/caddy; caddy list-modules | grep -E "rate_limit|gcs"' 3.20.4 v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk= -rwxr-xr-x 1 root root 41582744 Apr 27 08:56 /usr/bin/caddy caddy.storage.gcs ``` Three things are wrong at once: alpine **3.20.4** where the pinned base resolves to 3.23.5, Caddy **v2.8.4** where the Dockerfile builds 2.11.x, a `/usr/bin/caddy` timestamped **Apr 27**, and **`http.handlers.rate_limit` absent**. That last one is decisive: `caddy.Dockerfile` asserts on that module at build time (`caddy list-modules | grep -qE '^http\.handlers\.rate_limit$'`), so the published image cannot be the output of that Dockerfile. Its `apk` database also reports alpine 3.20.4 while a fresh build of the same file reports 3.23.5. Cost of that in the artifact consumers actually pull (`trivy image`, published `:latest` tags): | published image | C | H | M | L | total | |---|---|---|---|---|---| | `simplecontainer/caddy:latest` | **6** | 69 | 68 | 27 | 170 | | `simplecontainer/github-actions:latest` | **2** | 67 | 51 | 8 | 128 | | `simplecontainer/cloud-helpers:aws-latest` | 0 | 73 | 13 | 1 | 87 | | `simplecontainer/kubectl:latest` | 0 | 21 | 38 | 24 | 83 | Among caddy's 6 CRITICALs: `smallstep/certificates` v0.26.1 (CVE-2025-44005, CVE-2026-30836), `grpc` v1.64.0 (CVE-2026-33186), `libcrypto3`/`libssl3` 3.3.2-r1 (CVE-2026-31789), Go `stdlib` v1.23.4 (CVE-2025-68121) — plus the four Caddy admin-socket / fastcgi auth-bypass HIGHs (CVE-2026-27586/27587/27588/27590) that `caddy.Dockerfile`'s own header claims to have closed. This matters more than usual because the SC composite actions run these images by floating tag rather than digest, so consumers inherit whatever `:latest` points at. **Probable mechanism, and the change here.** Every `docker/build-push-action` step in the repo used `cache-from: type=gha` / `cache-to: type=gha,mode=max` with **no `scope:`**, so all builds shared one cache namespace: the 5-way image matrix in `push.yaml` (all writing `mode=max` concurrently), both images in `build-staging.yml`, and the preview matrix in `branch-preview.yaml`. Concurrent `mode=max` writers into a single GHA cache scope is a known way to get cache-index collisions across unrelated Dockerfiles. This PR scopes the cache per build — see **Round 2** below, which corrects the first attempt at this: scoping per *image* still let `push.yaml` and `branch-preview.yaml` collide on `github-actions`, so the final design keys scopes by **trust tier**. I want to be precise about confidence: the *observation* above is proven by direct execution, and unscoped shared cache is the most plausible mechanism, but I have not reproduced the collision inside GitHub's cache backend. If the next release still publishes a stale caddy after this lands, the next place to look is the welder image-build path rather than buildx. Either way scoping the cache is correct on its own merits. ## Documented unfixable (12 remaining, 0 CRITICAL) Every residual finding lives in a third-party prebuilt binary that we do not compile, each already at the newest published version. No `.trivyignore`, no VEX statement added for any of these — a scanner finding against a current upstream artifact is honest signal and should keep showing until upstream ships. **`/usr/local/bin/kubectl` (8) — upstream Kubernetes v1.36.3.** `golang.org/x/net` v0.49.0 (CVE-2026-25681, CVE-2026-27136, CVE-2026-39821, CVE-2026-33814 HIGH; CVE-2026-25680, CVE-2026-42502, CVE-2026-42506 MEDIUM) and `golang.org/x/text` v0.33.0 (CVE-2026-56852). *Reachability:* `kubectl` here is a CI-driven CLI speaking TLS to a trusted, authenticated API server endpoint; the x/net HTTP/2 and proxy parsing paths need a hostile server or hostile URL, and the x/text issue is an infinite loop on invalid input (DoS of a short-lived CI process). `alpine/kubectl:latest` is already the newest digest. *Closes when:* upstream k8s rebuilds against x/net ≥ 0.55.0. **`/usr/bin/caddy` (3) — vendored into Caddy v2.11.4's own module graph.** `x/text` v0.37.0 (CVE-2026-56852), `grpc` v1.81.0 (`GHSA-hrxh-6v49-42gf`, xDS RBAC fail-open + HTTP/2), `cel-go` v0.28.1 (`GHSA-gcjh-h69q-9w9g`, `json:"-"` fields readable from CEL). *Reachability:* Caddy is genuinely internet-facing, so these deserve the least benefit of the doubt — but both non-`x/text` findings sit in features this build does not use. The grpc advisory is scoped to `internal/xds/rbac` and the HTTP/2 *server* transport; Caddy links grpc as a client for its own internals and has no xDS RBAC authorization engine. `cel-go` is reached only through `ext.NativeTypes(ParseStructTag("json"))` over user-submitted CEL, which requires a CEL expression surface this build does not expose (the plugin set is `certmagic-gcs` + `caddy-ratelimit`). Overriding Caddy's module graph via xcaddy would mean shipping a Caddy built against dependency versions upstream has not tested, which trades a narrow unreachable finding for a broad untested one. *Closes when:* Caddy 2.11.5+ ships. **`/opt/google-cloud-sdk/bin/gke-gcloud-auth-plugin` (1) — Google-built, gcloud 579.0.0 (newest).** `x/text` v0.38.0, CVE-2026-56852. *Reachability:* a short-lived credential helper parsing Google's own token responses, not attacker-supplied text; the advisory is an infinite loop on invalid input. *Closes when:* Google rebuilds the plugin against x/text ≥ 0.39.0. **`/usr/local/bin/aws-lambda-rie` (4, grype only) — AWS-built, part of `lambda/provided:al2023`.** `x/sys` v0.21.0 (`GO-2026-5024`), `go-chi/chi/v5` v5.2.4 (`GO-2026-5774/5775/5777`). *Reachability:* the Runtime Interface Emulator is a local-testing shim AWS ships in the base image; it is not the entrypoint (`ENTRYPOINT ["/cloud-helpers"]`) and never runs in Lambda. *Closes when:* AWS refreshes the base image. **`py3-cryptography` 47.0.0 (4, grype only) — Alpine's newest, in `github-actions`.** `GHSA-537c-gmf6-5ccf`, `GHSA-jwv3-5hgf-82ww`, `GHSA-g6cj-pr64-35w5` (HIGH), `GHSA-m2h6-j472-rp4c` (MEDIUM). The fixes need 48.0.1 / 49.0.0 / 50.0.0, and Alpine ships 47.0.0-r0 on **both 3.24 and edge** — there is no branch to bump to. *Reachability:* pulled in by apk-managed `aws-cli` and used by gcloud auth; the PKCS#7 Bleichenbacher oracle and the `permittedSubtrees` wildcard escape need attacker-controlled PKCS#7 blobs or hostile certificate chains, neither of which is on the CI credential path. *Why not force it:* `pip install cryptography>=48` over the apk package would break Alpine's `externally-managed-environment` marker and desynchronise the `aws-cli`/gcloud dependency set — worse than the finding. The 3.23 → 3.24 bump in this PR already moved it 46.0.7 → 47.0.0. *Closes when:* Alpine packages 48.0.1+. Note this is a real trivy/grype split worth knowing: trivy scores `py3-cryptography` as an Alpine package with no distro fix and stays quiet, grype catalogues the same files as a PyPI dist-info and matches the GHSA advisories. Neither is wrong. Both tools are run here for exactly this reason. ## VEX re-triage `vex/openvex.json` v2 → v3. Nothing was added; two statements were corrected and one re-confirmed. | advisory | was | now | why | |---|---|---|---| | GO-2022-0635 (CVE-2020-8911) | `fixed` | `not_affected` / `component_not_present` | see below | | GO-2022-0646 (CVE-2020-8912) | `fixed` | `not_affected` / `component_not_present` | see below | | GO-2026-5932 (x/crypto/openpgp) | `not_affected` / `vulnerable_code_not_present` | unchanged, evidence re-verified | grep and call-path evidence still hold; `x/crypto` v0.54.0 is the latest release | **The two `fixed` statements were not fixable, and that made them indefinite suppressions.** OSV lists both aws-sdk-go advisories with `{"introduced": "0"}` and **no fix event** — AWS never patched the v1 `s3crypto` client, the remediation is migrating to the V2 encryption client. So `fixed` described a state that could never be reached, while still suppressing the finding in any VEX-aware scanner. The prior `impact_statement` also asserted the module had "left `go.mod` entirely through Go module pruning", which is not what the tree shows: ``` $ go list -m all | grep '^github.com/aws/aws-sdk-go ' github.com/aws/aws-sdk-go v1.55.8 # present in the requirement graph $ go list -deps ./... | grep -c '^github.com/aws/aws-sdk-go/' 0 # zero packages linked into any binary $ go mod why -m github.com/aws/aws-sdk-go (main module does not need module github.com/aws/aws-sdk-go) ``` `component_not_present` is the accurate justification: the module is a requirement-graph edge from a transitive `go.mod`, no package from it reaches the linker, and `s3crypto` specifically is never imported (S3 goes through aws-sdk-go-v2). Neither `govulncheck -mode=source` nor `osv-scanner` reports these against the repo, so no `osv-scanner.toml` mirror entry is needed; the header comment there is updated to say why they stay out and under what condition they would come back. `osv-scanner.toml` keeps exactly one `IgnoredVulns` entry (GO-2026-5932), unchanged. `CODEOWNERS` already gates `/vex/` and `/osv-scanner.toml`. ## Dependabot reconciliation All 7 open bot PRs are superseded by this one. Note `.github/dependabot.yml` is deliberately configured so majors fall outside the version groups and open individual PRs "for isolated review/testing" — that config is working as designed and is left untouched; this PR is the isolated review. | PR | What it proposed | Action | Why | |---|---|---|---| | #374 | `go-git/v5` 5.19.1 → 5.19.2 (`gomod-security`) | superseded | identical bump; also closes Dependabot alerts #75/#76 | | #371 | github-actions group, 8 updates | superseded | all 8 included, same SHAs | | #352 | `actions/cache` 5.0.5 → 6.1.0 | superseded | included; also fixes the stale `# v4.3.0` comment it would have left behind | | #351 | `actions/cache/save` 5.0.5 → 6.1.0 | superseded | included. Its checks were red (`SBOM + Dependency Scan`, `Security Status`) on the go-git baseline, which this PR clears | | #334 | `actions/checkout` 6.0.3 → 7.0.0 | superseded, **improved** | went to v7.0.1 instead; v7.0.0 predates the `--unset` escaping fix | | #333 | `alpine` 3.23 → 3.24 | superseded | same digest `28bd5fe8…` | | #326 | `caddy` digest `f2b9891` → `ea6e54f` | superseded, **improved** | that digest was already stale (opened Jun 15; upstream rebuilt Jul 7). Used the current `198d47ea…` / `844f60b6…` instead | Two Dependabot alerts (#75 HIGH, #76 MEDIUM) are the only open ones and both close on merge. ## Follow-ups, not done here - **`reecetech/version-increment` is pinned at `2024.10.1`; `2026.8.4` is out** (`28d33de033e97a304f77238d6a5db26039ca15d6`). Not bumped on purpose: no CVE, and the diff touches `version-increment.sh` + `shared.sh`, the calver logic that decides every release tag in `push.yaml` and `branch-preview.yaml`. Changing release versioning inside an SCA PR is the wrong blast radius. Worth its own PR with a dry-run. - **`simple-container-com/actions` refs are inconsistent**: 8 pins at `0af5a697…` and `semgrep.yml` at `5061c0a2…`, both commented `# main`. Not a vulnerability, but the drift is worth a sweep. ## Evidence <details><summary>Source scanners, this branch</summary> ``` $ trivy fs --severity CRITICAL,HIGH,MEDIUM,LOW . main: HIGH github.com/go-git/go-git/v5 v5.19.1 -> 5.19.2 CVE-2026-71556 MEDIUM github.com/go-git/go-git/v5 v5.19.1 -> 5.19.2 CVE-2026-71557 branch: 0 findings $ govulncheck -mode=source ./... 0 reachable; 1 module-level (GO-2026-5932, VEX not_affected) $ osv-scanner scan source -L go.mod main: 2 vulnerabilities (1 HIGH, 1 MEDIUM), 2 fixable branch: No issues found (GO-2026-5932 filtered, justified) $ pip-audit -r docs/requirements.txt No known vulnerabilities found ``` </details> <details><summary>Base-image layers, old digest vs new</summary> ``` alpine:3.23 (old) C=0 H=2 M=8 L=20 total=30 alpine:3.24 (new) C=0 H=0 M=0 L=0 total=0 caddy:2.11.4 (old) C=0 H=12 M=23 L=20 total=55 caddy:2.11.4 (new) C=0 H=10 M=15 L=0 total=25 alpine/kubectl old C=0 H=20 M=28 L=20 total=68 alpine/kubectl new C=0 H=5 M=3 L=0 total=8 lambda al2023 old C=0 H=58 M=5 L=1 total=64 lambda al2023 new C=0 H=0 M=0 L=0 total=0 217 -> 33 ``` </details> <details><summary>python base image comparison (welder build-docs)</summary> ``` python:3.9.18 C=248 H=2293 M=5849 L=1720 total=10110 (EOL Oct 2025) python:3.12 C=60 H=334 M=687 L=1178 total=2259 python:3.12-slim C=4 H=23 M=86 L=99 total=212 <- chosen python:3.13-slim C=4 H=19 M=56 L=66 total=145 ``` 3.12-slim over 3.13-slim on purpose: `docs/requirements.txt` is `pip-compile`d for Python 3.12 with `--generate-hashes`, so 3.12 is the version the lockfile was resolved against. The 67-finding gap is all LOW/MEDIUM distro noise. Build verified end to end against the real lockfile: ``` $ docker run --rm -v "$PWD/docs:/w" -w /w python:3.12-slim sh -c \ 'pip install -r requirements.txt && mkdocs build' INFO - Documentation built in 2.86 seconds ``` (The pre-existing `ai-assistant/examples/*` broken-link warnings are unchanged and unrelated.) `mkdocs.yml` uses only `search` + `mermaid2`, no git-dependent plugins, so `-slim` is sufficient. </details> ## Test plan - `go mod tidy` clean; `go build ./cmd/github-actions ./cmd/cloud-helpers` succeeds. Our own `dist/github-actions` links `golang.org/x/text v0.40.0` (patched) per `go version -m`. - All 5 images build from a clean context on both `origin/main` and this branch; the before/after tables above come from those builds, not from published tags. - `caddy` image smoke-verified post-bump: v2.11.4, alpine 3.23.5, both `caddy.storage.gcs` and `http.handlers.rate_limit` registered, so the Dockerfile's build-time module assertion passes. - `github-actions` image build-time smoke test (`pulumi version`, `gcloud version`, `gke-gcloud-auth-plugin` present, `aws --version`, `sc` symlink) passes on alpine 3.24 + gcloud 579.0.0. - docs build verified in `python:3.12-slim` against the real hashed lockfile. - Action SHAs verified against the GitHub git-ref API with annotated tags dereferenced; no pin was hand-written. --- # Round 2: multi-model review + preview build Six independent reviewers (four Claude lenses, OpenAI Codex, Google Gemini). Every claim below was re-verified before acting on it; two findings were defects in round 1's own diff, and one review claim turned out to be a probe artifact. ## Verified in a real pipeline `branch-preview.yaml` dispatched twice, once per commit. Both **13/13 jobs green**, including the docker builds — the second run with fully cold caches, since every scope name changed. | | round 1 (`35cde9a`) | round 2 (`64ddbee`) | |---|---|---| | preview version | `v2026.8.4-pre.35cde9a-preview.35cde9a` | `v2026.8.4-pre.64ddbee-preview.64ddbee` | | `github-actions` image | C0 **H1** M0 — total 1 | C0 **H1** M0 — total 1 | | `cloud-helpers` image | — | C0 H0 M0 — **total 0** | The CI-built image reports `alpine 3.24.1`, `Google Cloud SDK 579.0.0`, `pulumi v3.245.0`, `gke-gcloud-auth-plugin` present. Against the published `:latest` from main (128 findings, 2 CRITICAL) that is **128 → 1**, and the one residual is the documented `x/text v0.38.0` inside Google's auth plugin. The gcloud `SHA256` pin verified inside a real build, which is the authoritative check on that value. ## Two defects in round 1's own diff **1. The cache scoping was wrong, not merely inconsistent.** Round 1 scoped per image — but `github-actions` is a matrix value in *both* `push.yaml` (`matrix.image`) and `branch-preview.yaml` (`matrix.target`), so they collided on one scope. `branch-preview` is dispatchable from any branch and `mode=max` exports builder stages, so a preview build could seed the very layer a release build restores — and a cache hit means the SHA-256-verified gcloud and Pulumi downloads never execute. Round 1 separated staging but not preview, which made the gap easy to miss. Scopes are now keyed by **trust tier**: releases read and write `prod-*` only; staging and preview write their own tier and read `prod-*` as a warm fallback, which is the safe direction (reading higher-trust cannot poison it). `branch-preview` gained an explicit `cache_scope` so its fallback matches push.yaml's image naming (`cloud-helpers-aws`, not `cloud-helpers`) — Gemini and two Claude lenses independently flagged that mismatch. Expect one cold release build after merge; that is the scope rename, not a regression. **2. `welder.yaml` weakened a pin.** Round 1 replaced `python:3.9.18` with a floating `python:3.12-slim` and a bare `pip install`, against this repo's own documented digest-pin + `--require-hashes` policy — while `push.yaml:376` already pinned the same tool by digest. Now digest-pinned and hash-enforced, identical to the CI docs build, and **both** refreshed to the current digest (round 1 left push.yaml's three months stale). ## Pre-existing defects the panel surfaced **The Pulumi integrity gate could not fail the build.** `... && sha256sum -c - && ... && strip … || true && upx … || true` parses as `((chain || true) && upx) || true`: `&&` and `||` are equal precedence and left-associative, and errexit does not apply to non-final commands in an AND-OR list. Verified both ways — with a deliberately wrong expected hash, the old shape exits **0**, the brace-grouped shape now **fails**: ``` #8 1.650 sha256sum: WARNING: 1 of 1 computed checksums did NOT match #8 ERROR: process "/bin/sh -c set -euo pipefail ..." did not complete successfully: exit code: 1 ``` The gcloud chain terminates on a real command and was already fail-closed, so the gcloud claim in this PR was accurate. Fixed in both github-actions Dockerfiles. **`simplecontainer/cloud-helpers:aws-latest` cannot start.** `actions/upload-artifact` does not preserve the executable bit, and `push.yaml` has no `chmod` for this binary — `branch-preview.yaml:324` does. The published image has `/cloud-helpers` at `-rw-r--r--` with `ENTRYPOINT ["/cloud-helpers"]`. Asserted in the Dockerfile rather than a workflow so it holds whichever path builds it; the CI-built preview image now reports `-rwxr-xr-x`. **Docs example images carried the CVEs this PR claims to close.** `docs/DEPENDENCIES.md` lists example dirs in the tracked Docker surface, but `dependabot.yml` scanned only the root level and rationalised the gap in a comment. `blog-platform/caddy.Dockerfile` pinned caddy **2.11.3** — the exact version whose CVEs this PR fixes at the root — and six files pinned node **22.22.3** (CVE-2026-48618, CVE-2026-48933, both HIGH; fixed in 22.23.0). All bumped to digests re-resolved against the live registry, the docker ecosystem now globs `docs/docs/examples/**`, and one example moves off EOL `python:3.9`. ## Caddy: version now single-sourced from the base image Rather than keep three `2.11.x` literals guarded by a comment, `xcaddy` now builds `"${CADDY_VERSION}"` — the env var the caddy base images set themselves. There is no second literal to forget, which is precisely what shipped a 2.11.3 binary on a 2.11.4 base. Both stages assert the built binary against their own base's version, and `certmagic-gcs` joins `rate_limit` in the module assertions (a silently dropped storage plugin means per-pod ACME state and Let's Encrypt lockout). Worth recording how this landed: my first attempt compared the binary to a hand-maintained `ARG`, and the negative test showed it passing on a deliberate skew — self-consistent by construction, proving nothing. My second negative test was also invalid, because the digest I picked for "2.11.3" was actually the old 2.11.4 rebuild. Only the third attempt, against the genuine `caddy:2.11.3` digest, demonstrated the gate firing: ``` ERROR: process "/bin/sh -c test -n \"${CADDY_VERSION}\" && caddy version | grep -qF \"${CADDY_VERSION} \"" did not complete successfully: exit code: 1 ``` ## VEX corrections The GO-2026-5932 statement claimed x/crypto was "a direct dependency for chacha20poly1305 only" while stamped *re-confirmed against the current tree*. It is not: **24** x/crypto packages link, including `ssh`, `ssh/agent`, `ssh/knownhosts`, `pkcs12` and `ocsp`, and `pkg/api/secrets` imports `ssh` directly. The conclusion is unchanged — openpgp linkage is 0 — but understating the linked surface on the one artifact an auditor reads is worse than not writing it, and `x/crypto/ssh` is the subpackage with the CVE history. Two reviewers caught this independently. The evidence commands now specify `-buildvcs=false`: a plain `go list -deps` can exit non-zero on a VCS error and print nothing, which greps identically to a clean result — the same masking failure mode as `|| true`. On the aws-sdk-go statements, one reviewer argued `component_not_present` contradicts an impact_statement that mentions `go list -m all`, and proposed `vulnerable_code_not_present`. I kept `component_not_present` and made the scope explicit instead: for the shipped artifact the component genuinely is absent — 0 packages linked, **0 `go.sum` entries**, 0 in the built binary's BuildInfo — and the residual `go list -m all` edge is a requirement-graph reference from a transitive `go.mod`. `vulnerable_code_not_present` would wrongly imply the component ships and only the vulnerable function is absent. ## Doc contracts this pass contradicted `DEPENDENCIES.md` stated that every `not_affected` is mirrored into `osv-scanner.toml`, and that a superseded one gets flipped to `status: fixed` — the rule that produced the bug round 1 reverted. Both are now qualified: the mirror covers only advisories osv-scanner actually reports (an unused ignore is itself a finding), and an advisory with `introduced: 0` and no fix event can never reach `fixed`. ## One review claim that did not survive Codex reported a **different gcloud SHA-256** than the pin. That was its own probe artifact: it fetched with `curl -C -` (resume) against a leftover file, producing 97,127,837 bytes and `gzip: trailing garbage ignored`. A clean download is 96,066,973 bytes hashing to `a9a7fbe5…`, matching the pin — and CI's own verification passed inside the preview build. No change needed. Codex otherwise reported clean. ## Deliberately deferred These are real but wrong to fold into a dependency PR: - **go-git 5.19.2 hardens worktree paths.** One lens demonstrated that `AddFileToGit` now rejects a path whose leading component is a symlink (`pkg/provisioner/common.go` passes `.sc/cfg.yaml.template`), where 5.19.1 accepted it — and that the test suite passes on *both* versions, so nothing would catch it. The repo has zero `os.Symlink` usage in tests. Reverting would reintroduce the CVEs, so the fix is a test plus an actionable error message, and it needs a decision on whether a symlinked `.sc` is a supported layout. Worth its own issue. - **`reecetech/version-increment`** at `2024.10.1` (latest `2026.8.4`, SHA `28d33de0`). Its diff touches the calver logic that names every release tag. - **`github-actions-staging.Dockerfile` duplicates ~95 lines** of its sibling under a "keep in sync" comment; this PR had to edit the alpine digest and both gcloud ARGs twice. - **A pin-consistency CI gate** (action SHA vs its `# vX.Y.Z` comment, gcloud version/SHA parity across the two Dockerfiles). Round 1 found a `# v4.3.0` comment on a v5.0.5 SHA by hand; a 20-line `gh api` check would have caught it. `# v4` on the codeql pins is corrected to `# v4.37.6` here. - **`DEPENDENCIES.md` claims `trivy image` runs per published image** — no trivy/grype step exists in any workflow; the shared scan is source-tree only. That is why the stale caddy binary went unnoticed for months. - **No PR-time build of any Dockerfile**; the first build happens post-merge on `push.yaml`. A `docker build --load` job on a path filter would close it. - `certmagic-gcs` v0.1.7→v0.1.8, `golangci-lint` v1→v2, pulumi SDK 11 minors, `mermaid` 10.6.1 in the docs site. --------- Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps the docker group with 1 update in the / directory: alpine.
Updates
alpinefrom 3.23 to 3.24