feature/support ed25519 keys for encryption and decryption - #8
Merged
Conversation
Cre-eD
approved these changes
Sep 28, 2025
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.
Add Ed25519 Public Key Support and SSH Key Alias Normalization
🔐 Ed25519 Cryptographic Support
New Functions Added:
Cryptor Integration:
🔧 SSH Key Alias Normalization
Key Improvements:
🧪 Testing
📋 Files Modified
🚀 Impact