Skip to content

fix: bump dependencies to clear all known CVEs - #402

Merged
alexey-igrychev merged 5 commits into
mainfrom
fix-cve
Jul 29, 2026
Merged

alexey-igrychev merged 5 commits into
mainfrom
fix-cve

Conversation

@alexey-igrychev

Copy link
Copy Markdown
Member

Supersedes #401, whose commit is included here as the first commit.

Brings all four modules to zero known vulnerabilities.

Module Before After
client 11 0
server 20+ 0
release 8 0
e2e 20 0

Why #401 needed follow-up

It left two of four modules unbuildable:

  • e2e/go.mod was never re-tidied after the client/server bumps, so the module failed outright with updates to go.mod needed and still pinned the vulnerable go-git v5.12.0, circl v1.3.7 and ProtonMail/go-crypto v1.0.0.
  • release/ was untouched, but it replaces ../client, so its go 1.23.2 directive broke against client's bumped one.

Neither of the two CI jobs that build e2e could have passed.

Go version

All four modules now declare go 1.25.0 plus toolchain go1.25.12. The split matters:

  • 1.25.0 is the minimum x/tools and otel/trace require, and keeping the language version there leaves room for tools built with older toolchains.
  • the toolchain line is what actually closes the stdlib advisories. They have no Go 1.24 backport — the affected ranges are [0, 1.25.9/10/11/12) — and actions/setup-go prefers toolchain over go when reading go-version-file.

lint.yaml no longer hardcodes go-version: "1.24"; it reads go-version-file like every other workflow. The builder image moves to golang:1.25.12-bookworm.

golangci-lint v1 -> v2

Raising the go directive past 1.24 makes golangci-lint v1.64.2 unusable: its prebuilt binary is compiled with go1.24 and cannot parse go 1.25 packages at all, so it fails in typecheck and --go=1.24 does not help. v2.11.0 is the newest release that common-ci's installer can actually fetch (v2.12.x fails checksum verification) and that is built with a new enough Go.

v2's config format is incompatible with the v1 config shared via werf/common-ci, so a local .golangci.yml is vendored. It was translated by hand rather than with golangci-lint migrate, whose output silently adds exclusion presets (comments, common-false-positives, legacy, std-error-handling) that would have weakened linting.

The gofumpt bundled in v2.11.0 rewrites naked returns to explicit ones, which is what CODESTYLE.md asks for anyway — hence the small diffs in client/pkg/repo, client/pkg/util and server/pkg/git.

openpgp migration

golang.org/x/crypto/openpgp is unmaintained upstream and carries GO-2026-5932, which has no fixed version — the only way out is a different implementation. server/pkg/pgp was the sole importer in the server graph, so switching it removes the package entirely.

This adds no new dependency: ProtonMail/go-crypto was already in the graph as an indirect requirement of go-git, so the server now has one OpenPGP implementation instead of two. The fork is API-compatible except for CheckArmoredDetachedSignature, which takes a trailing *packet.Config. Defaults line up — an unset Config.Algorithm means RSA and V6Keys defaults to false, so generated keys stay v4.

Since trdl stores PGP signing keys in Vault and verifies user-supplied trusted public keys, the real risk here is backward compatibility rather than compilation. server/pkg/pgp/testdata/ holds fixtures generated by the previous x/crypto code — an armored private key, its public key, a binary detached signature, and an armored signature produced by the real gpg binary from that same key — and openpgp_compat_ai_test.go asserts the new code still parses and verifies all of them. The test was confirmed to fail when a fixture is tampered with. The pre-existing suite proves the other direction: a key generated and signed by ProtonMail/go-crypto is accepted by gpg --verify.

format/lint no longer disagree

task format and task lint contradicted each other: common-ci pins gofumpt v0.7.0, while golangci-lint v2.11.0 bundles v0.11.0. Following nelm, each module now owns its format and lint tasks and both call the same golangci-lint binary — run --fix to format, run to lint — so gci and gofumpt come from one place and cannot drift apart. The common-ci include stays for prettier, namespaced as ci: rather than flattened, because Task rejects duplicate task names and a flattened include cannot be partially overridden.

Still unfixable

Nothing remains in govulncheck. For the record, the docker daemon-side advisories (GO-2026-5668 / 4887 / 4883, fixed only in the pre-release moby/moby/v2) went away because #401 deleted RemoveImagesByLabels, which was dead code and the last thing pulling docker/docker into the server.

Verified locally

task build:dev:all · task lint (0 issues in all four modules) · task server:test:unit (9/9 suites) · task client:test:unit · builder image builds and reports go1.25.12 · govulncheck on all four modules.

Not runnable on macOS, so CI is the first real check: the e2e elf_signing suite behind //go:build linux && amd64 && cgo.

trublast and others added 5 commits July 29, 2026 21:36
Complete the work started in #401, which left the tree unbuildable:

- e2e/go.mod was never re-tidied after the client/server bumps, so the
  module failed with "updates to go.mod needed" and still pinned the
  vulnerable go-git v5.12.0, circl v1.3.7 and ProtonMail/go-crypto v1.0.0.
- release/ was untouched, but replaces ../client, so its go 1.23.2
  directive broke against client's bumped one. Its go-jose is now v4.1.4.

All four modules now declare `go 1.25.0` (the minimum x/tools and
otel/trace require) plus `toolchain go1.25.12`. The split matters: the
toolchain line is what closes the stdlib advisories, which have no Go 1.24
backport, and actions/setup-go prefers it over the go directive. Keeping
the language version at 1.25.0 leaves room for tools built with older
toolchains.

Raising the go directive past 1.24 makes golangci-lint v1.64.2 unusable —
its prebuilt binary is compiled with go1.24 and cannot parse go1.25
packages at all, so --go=1.24 does not help. Move to v2.11.0, the newest
release that common-ci's installer can fetch and that is built with a new
enough Go. Its config format is incompatible with the v1 config shared via
werf/common-ci, so vendor a local .golangci.yml translated by hand rather
than via `golangci-lint migrate`, whose output silently adds exclusion
presets that would weaken linting.

The gofumpt bundled in v2.11.0 rewrites naked returns to explicit ones,
which is also what CODESTYLE.md asks for.

Also bump the builder image and drop lint.yaml's hardcoded Go version in
favour of go-version-file, so it tracks go.mod like every other workflow.

Remaining, both unfixable upstream: GO-2026-5932 (x/crypto/openpgp is
unmaintained with no fixed version; needs pkg/pgp migrated to
ProtonMail/go-crypto) and the docker daemon-side advisories, which #401
already sidestepped by deleting the unused RemoveImagesByLabels.

Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
golang.org/x/crypto/openpgp is unmaintained upstream and carries
GO-2026-5932, which has no fixed version — the only way out is a different
implementation. pkg/pgp was the sole importer in the server graph, so
switching it removes the package entirely and brings all four modules to
zero known vulnerabilities.

This adds no new dependency: ProtonMail/go-crypto was already in the graph
as an indirect requirement of go-git, so the server now has one OpenPGP
implementation instead of two.

The fork is API-compatible except for CheckArmoredDetachedSignature, which
takes a trailing *packet.Config. Defaults line up with the old behaviour:
an unset Config.Algorithm means RSA and V6Keys defaults to false, so
generated keys stay v4.

Because trdl stores PGP signing keys in Vault and verifies user-supplied
trusted public keys, the risk here is backward compatibility rather than
compilation. Add fixtures generated by the previous x/crypto code — an
armored private key, its public key, a binary detached signature, and an
armored signature produced by the real gpg binary from that same key — and
assert the new code still parses and verifies all of them. Verified the
test fails when a fixture is tampered with.

Note that these fixtures were checked with the gpg CLI, and the existing
suite continues to prove the other direction: a key generated and signed
by ProtonMail/go-crypto is accepted by gpg --verify.

Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Drop the ai_tests build tag from the pgp compatibility test. The tag kept
it out of `task server:test:unit`, so the one check guarding backward
compatibility of stored PGP keys never ran in CI — which defeats its
purpose.

Ignore /release/bin and /release/dist. The former is where
`task release:build:dev:all` lands its binaries, and I already committed
40MB of them by accident twice while working on this branch. /release/dist
is the same omission for `release:build:dist`, next to the /client/dist and
/server/dist entries that were already there.

Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
`task format` and `task lint` disagreed: common-ci pins gofumpt v0.7.0 via
deps:install:gofumpt, while golangci-lint v2.11.0 bundles gofumpt v0.11.0.
Formatting the tree then linting it produced errors, because the newer
gofumpt rewrites naked returns and the older one does not. There is no
variable to override the pinned version, so the desync cannot be fixed from
this repo as long as the two come from different binaries.

Adopt nelm's arrangement, which makes the desync impossible by
construction: each module now owns its `format` and `lint` tasks and both
call the same golangci-lint binary — `run --fix` to format, `run` to lint.
gci and gofumpt come from the `formatters` section of .golangci.yml, so
there is exactly one source of formatting behaviour.

The common-ci include stays for prettier, but namespaced as `ci:` rather
than flattened, since a flattened include cannot be partially overridden —
Task rejects duplicate task names outright.

Dropping the per-module `paths` vars is not a behaviour change: they only
fed the standalone gci and gofumpt invocations. golangci-lint takes ./...
and honours the exclusion paths already declared in .golangci.yml. No
module set `mode: cgo`, so lint was already a single CGO_ENABLED=0 pass and
still is.

Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
@alexey-igrychev
alexey-igrychev merged commit 31430e1 into main Jul 29, 2026
24 checks passed
@alexey-igrychev
alexey-igrychev deleted the fix-cve branch July 29, 2026 19:43
alexey-igrychev added a commit that referenced this pull request Jul 29, 2026
#402 raised every module to `go 1.25.0` and moved
trdl-builder.Dockerfile to golang:1.25.12-bookworm, but it was merged
before the commit that repinned the manifests. So main now asks for
go >= 1.25.0 while release builds still run inside a builder image built
from golang:1.24 — a release cut from main would fail with
"module requires go >= 1.25.0", which is the same breakage #402 set out to
fix.

Repin all three module manifests to registry.werf.io/trdl/builder:0c698d2,
published from the branch of #402. Its tree is identical to the squashed
commit on main, so the image is exactly what landed.

Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants