Skip to content

fix: backport three security fixes from 0.71/0.72 - #212

Merged
kycheng merged 4 commits into
alauda-v0.68.2from
fix/backport-cve-20260908
Sep 8, 2026
Merged

kycheng merged 4 commits into
alauda-v0.68.2from
fix/backport-cve-20260908

Conversation

@kycheng

@kycheng kycheng commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

harbor-helm restored its per-image trivy gate to exitCode 1, and the scan of goharbor-trivy-adapter-photon then failed on three findings in the trivy binary itself - all fixed only on release lines newer than this one:

Severity CVE Issue Upstream fix
HIGH CVE-2026-54448 Helm chart tar bomb: the custom archive parser reads each entry with unbounded io.ReadAll, so a small .tgz can expand to gigabytes and OOM the scanner 0.71.0 (#10718)
HIGH CVE-2026-55092 Path traversal: an OCI artifact org.opencontainers.image.title annotation is used as the destination filename without validation 0.71.1 (a72d9a4d)
MEDIUM CVE-2026-63328 Path traversal in the plugin manager: plugin manifest metadata builds paths under ~/.trivy/plugins without confining them to that root 0.72.0 (d4213d77)

Moving this fork to 0.71/0.72 would mean four minor versions of behaviour change to re-validate against harbor-scanner-trivy, so this backports the fixes instead.

What is in here

  1. a72d9a4d cherry-picked as-is (CVE-2026-55092) - clean, 2 files, +36/-1.

  2. d4213d77 cherry-picked (CVE-2026-63328) - one import conflict only; brings upstream pkg/x/os/root.go (rooted writes) plus the absolute_name / escaping_name plugin test data. The unused xslices import is dropped: upstream had also refactored lo.Map to xslices.Map, which this branch does not have.

  3. CVE-2026-54448 reimplemented minimally. Upstream replaced the whole parser with the Helm SDK loaders - 143 files, +1746/-6984 - which is not backportable here. Instead unpackArchive now enforces the Helm SDK's own published limits, from the loader package this tree already depends on (helm.sh/helm/v3 v3.20.2):

    • loader.MaxDecompressedFileSize (5 MiB) per entry
    • loader.MaxDecompressedChartSize (100 MiB) per archive

    The archive budget is decremented by bytes actually read, via io.LimitReader(tr, remaining+1), so an entry whose real size exceeds its header is caught rather than trusted. Net +20 lines. A chart Helm itself would refuse to load is now refused here too.

Test plan

  • go build ./pkg/... ./cmd/... passes
  • go test ./pkg/iac/scanners/helm/... ./pkg/plugin/... ./pkg/oci/... green, including the two malicious-plugin cases the CVE-2026-63328 backport adds
  • After merge: cut v0.68.3-alauda-12, then bump TRIVY_VERSION in harbor-helm .tekton/all-in-one.yaml and confirm build-trivy-adapter-scan goes green on its own merit

🤖 Generated with Claude Code

knqyf263 and others added 3 commits September 8, 2026 22:58
Reject any filename that is not a local relative path via filepath.IsLocal before opening the destination file.

GHSA-mcj4-mphf-j9ff

(cherry picked from commit a72d9a4)
Adopt Go's os.Root for plugin file operations so that all path access
derived from a plugin name stays within the plugin root (~/.trivy/plugins).
Add pkg/x/os.Root, a small wrapper over os.Root with a Join helper, and
route install, uninstall, and plugin loading through it instead of joining
names onto the root path directly.

NewManager opens the plugin root eagerly and returns an error, and exposes
Close; the package-level Run/Start helpers wrap it for callers outside the
plugin subcommands.

(cherry picked from commit d4213d7)
Upstream fixed this in 0.71.0 by replacing the custom Helm archive parser
with the Helm SDK loaders (#10718) - 143 files, +1746/-6984. That is far too
much to backport onto this branch, so this applies the same protection to the
parser we have.

unpackArchive read every regular entry with io.ReadAll(tr) and no limit, so a
small crafted .tgz could expand to gigabytes and OOM the scanner. It now
enforces the Helm SDK's own published limits, taken from the loader package
this tree already depends on (helm.sh/helm/v3 v3.20.2):

  loader.MaxDecompressedFileSize   5 MiB  per entry
  loader.MaxDecompressedChartSize  100 MiB per archive

The per-archive budget is decremented by bytes actually read, via
io.LimitReader(tr, remaining+1), so a header that understates the entry size
is caught rather than trusted. A chart Helm itself would refuse to load is now
refused here too.

Also drops the unused xslices import that came in with the plugin-manager
backport: upstream had refactored lo.Map to xslices.Map in unrelated cleanup,
and this branch still uses lo.Map.

Verified: go build ./pkg/... ./cmd/... passes, and go test for
pkg/iac/scanners/helm/..., pkg/plugin/... and pkg/oci/... is green, including
the escaping_name / absolute_name plugin cases the CVE-2026-63328 backport adds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

📊 API Changes Detected

Semver impact: major

github.com/aquasecurity/trivy/pkg/x/os
  Compatible changes:
  - NewRoot: added
  - Root: added

github.com/aquasecurity/trivy/pkg/plugin
  Incompatible changes:
  - Information: removed
  - Install: removed
  - List: removed
  - NewManager: changed from func(...ManagerOption) *Manager to func(...ManagerOption) (*Manager, error)
  - Search: removed
  - Uninstall: removed
  - Update: removed
  - Upgrade: removed
  Compatible changes:
  - (*Manager).Close: added
  - DirExists: added

The two cherry-picked backports carry upstream tests (pkg/oci/artifact_test.go
for CVE-2026-55092; manager_test.go, manager_unix_test.go, pkg/x/os/root_test.go
and the absolute_name / escaping_name plugin fixtures for CVE-2026-63328). The
hand-written CVE-2026-54448 fix had none, so this adds one.

The test builds gzipped tars whose entries are zero bytes on disk but declare
large sizes - the shape of a decompression bomb - and asserts three things:
an entry over the per-file limit is rejected, entries that together exceed the
per-archive budget are rejected, and an archive within both limits still parses.

Helm exports its limits as vars, so the test lowers them and restores them in
t.Cleanup rather than building a 100 MiB fixture.

Confirmed to be a real regression test: with parser_tar.go reverted to the
pre-fix version both failing cases fail, and they pass again with the fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kycheng
kycheng merged commit 811363b into alauda-v0.68.2 Sep 8, 2026
6 of 9 checks passed
@kycheng
kycheng deleted the fix/backport-cve-20260908 branch September 8, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants