Vulnerabilities
apko / melange CVE-2026-54174 APK data-member integrity gap — the manifest passed while the cargo went unmatched
As reviewed on July 26, 2026, deploy apko 1.2.25 and melange 0.56.3, then recheck supported releases at deployment; 1.2.9 and 0.50.4 mark only the first-fixed boundary, and rollout must isolate old cache and pass a valid-package positive control plus independent control- and data-mismatch rejections because affected getters never compared .PKGINFO.datahash with the observed PackageHash .

In this article
The defect sits in the success conditions for a newly fetched APK. Affected apko already obtained an expected control digest from trusted APKINDEX and calculated SHA-256 over the data member it received. Once control passed, code handed the expanded object to cache or caller without the second equality. An actor influencing a mirror, delivery cache, or actual fetch response could preserve legitimate control while replacing data that entered the build root filesystem.
1 Upgrade first and isolate old cache: start the change ticket here
Decision: apko earlier than 1.2.9 and melange earlier than 0.50.4 enter response scope. The current change ticket deploys apko 1.2.25 and melange 0.56.3; these are the release targets at review time and must be rechecked against official release and support status during deployment. apko installs repository packages directly into a rootfs, while melange retrieves dependencies through apko for build and test guests. A compatibility rollback is acceptable only as an approved artifact carrying equivalent data comparison and passing all three qualification cases.
Before rollout, pause affected environments from fetching through mutable external mirrors, shared proxy caches, and local caches whose provenance is unknown. Preserve APKs, APKINDEX snapshots, cache files, and job logs needed for investigation in read-only form, then withdraw old cache from service. Temporary fetch restrictions reduce the set of systems able to alter a response. The fixed version remains necessary to enforce both in-format digest relationships.
1.1 Three consecutive gzip members establish two digest relationships
An APK v2 package is a sequence of gzip streams: an optional .SIGN member, a control member containing .PKGINFO, and a data member carrying files, directories, modes, and links. In melange v0.56.3, emitDataSection() lines 407–441 compress data and calculate SHA-256, while the control template at lines 165–199 writes its hexadecimal value into .PKGINFO.datahash. EmitPackage() lines 522–592 then create control, optionally sign the compressed control bytes, and combine final bytes as signature, control, data. An unsigned package contains control followed by data.
apko's ordinary repository path starts at a repository-index entry that verifies signatures by default; the signature gate at lines 308–425 runs before parsing, so an environment explicitly using ignoreSignatures lacks this premise. APKINDEX parser lines 189–197 decode Base64 SHA-1 after the Q1 prefix. Expander lines 453–574 calculate and assign ControlHash for control and PackageHash for data. The ordinary repository path relies on authenticated index and Q1. It does not reverify each package's optional .SIGN member. The four values form these two comparisons:
| Authenticated expectation | Observed value | Source and object | Decision |
|---|---|---|---|
decode(Q1), Base64-encoded SHA-1 | ControlHash | Verified APKINDEX declares the control gzip; the expander digests received control | First gate: inequality rejects; equality makes fields inside control trustworthy |
decode(.PKGINFO.datahash), hex-encoded SHA-256 | PackageHash | Control that passed the first gate declares the data gzip; the expander digests received data | Second gate: omitted before the fix; 1.2.9 closes the object and errors on inequality |
The report uses one integrity invariant from this point forward: decode(Q1) == ControlHash && decode(.PKGINFO.datahash) == PackageHash. The first gate joins index to control; the second joins authenticated control to data. PAX file checks inside the data tar examine internal structure. An actor replacing the complete data member can update both its files and the checks stored in that member, leaving source integrity to the second gate.
1.2 Code location, permanent repair, temporary controls, and exit criteria
Change-ticket summary: target apko 1.2.25 and melange 0.56.3 as reviewed, rechecking current official releases at deployment; retain 1.2.9 and 0.50.4 as the minimum fixed boundary. Prove that melange links apko 1.2.25 or an approved equivalent repair with go version -m, SBOM, or provenance; retire old process and disk caches after evidence preservation, start empty, and temporarily fetch only from approved authenticated snapshots; preserve valid-package positive-control semantics while control mismatch and data mismatch fail independently, with no cache, return, installation, or publication; discard the failed workspace and rebuild high-value historical images until old binaries, modules, caches, manifests, and downstream digest pins are removed or recorded as exceptions.
At the fix parent a7f10d8972fa035714387d9621745397a2f4135c, defaultPackageGetter.GetPackage() lines 97–126 coordinates cache, while getPackageImpl() lines 129–183 performs disk-cache lookup, fetch, expansion, and release. The old implementation enforces only the first gate at lines 173–176; it returns directly at lines 178–180 when disk cache is disabled and publishes a new cache object at line 183 when cache is enabled.
Fix commit 8d34c756b1acdec0d18c82247f900a54255500f5 keeps the same GetPackage() entry and extends getPackageImpl() through line 208. Lines 173–186 enforce the first gate. Lines 188–201 parse .PKGINFO from authenticated control, decode datahash, and enforce the second. A representation error or either mismatch calls exp.Close() and returns an error. Only two successful gates reach the return or cachePackage() branch at lines 203–208.
When a fixed getter cannot be deployed immediately, pause remote package retrieval and artifact promotion on the affected path. Narrowing the network, changing mirrors, clearing cache once, or changing only a displayed version leaves the missing success condition in place.
datahash before it creates control and the optional signature; apko's two comparisons join index, control, and data.2 The defect is in the success branch for a newly fetched object
GetPackage() and getPackageImpl() at lines 152–231 either execute directly or use singleflight for the same URL and first attempt disk cache. After a miss, doFetchExpandAndVerify() lines 260–303 read a local file, HTTP response, or HTTPS response, expand the APK, and enforce the control and data gates. Once expansion succeeds, control files, a data TarFS, and both observed digests already exist.
The relevant state change grants a readable object permission to become a consumable object. Parser success means the consecutive gzip and tar structures opened. Getter comparisons decide whether the resulting bytes may be returned, cached, and installed. The old path made first-gate success the whole integrity condition, leaving the calculated PackageHash outside authorization.
2.1 Before the fix, successful control leads directly to return or cache
Lines 168–171 of the fix parent complete expansion, and lines 173–176 call verifyControlHash(). A failed first gate closes the expanded object. A successful first gate returns when disk cache is absent or calls cachePackage() when it is present. PkgInfo().DataHash and PackageHash already coexist in the same object lifetime, yet neither enters the success predicate as a pair.
The first gate is real enforcement: an invalid Q1 representation, malformed Base64, or wrong control bytes fail. A suite containing only a valid package and a damaged-control case can therefore look complete. The data-mismatch test has to preserve control exactly so it isolates the missing relationship.
Cache hits require their own operational treatment. In the first-fixed commit, getPackageImpl() lines 142–145 may return a disk-cache object. Current v1.2.25 still returns a successfully loaded cache object at lines 200–204, with cachedPackage() lines 440–538 restoring it from stored control and data files. A binary upgrade does not automatically route every historical entry through the fresh-fetch gates. The rollout therefore preserves a read-only evidence copy, withdraws old cache from production, and rebuilds with an empty cache.
2.2 After the fix, the second gate precedes cache, return, and installation
Version 1.2.9 calls exp.PkgInfo() after the first gate and obtains DataHash from authenticated control. hex.DecodeString() converts representation; non-hex characters and odd length fail directly, while empty or incorrectly sized decodable text later fails equality against the thirty-two-byte PackageHash.
Second-gate failure follows the resource semantics of first-gate failure: close the expanded object, return an error, and stop the current object. The error is not downgraded to an ordinary network retry, and no partially qualified TarFS is handed over. This location removes an inconsistent newly fetched member before cache publication, package return, and installation consumption.
In current v1.2.25, TestGetPackage_HashVerification lines 336–372 exercise the public GetPackage entry with a valid-package positive control, a control mismatch, and a data mismatch. The positive case prevents unconditional rejection from masquerading as repair. Orthogonal negative controls preserve the old gate and establish the new gate independently. Downstream qualification should also cover malformed Base64, malformed hex, missing .PKGINFO, truncated gzip, signed and unsigned layouts, and absence of promotion side effects after failure.
3 Reachability depends on who can alter the APK the build actually receives
The maintainer advisory requires attacker influence over the APK obtained by a target builder: a compromised origin or mirror, a poisoned delivery cache, or a man in the middle modifying package fetch. The actor must also wait for the target to select the relevant index record and fetch it. Knowledge of a repository address, recipe submission, or read-only repository credentials provides no response-byte modification by itself.
The reviewed GitHub advisory assigns CVSS 3.1 score 8.3 with AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H. PR:N means the attacker needs no account on the vulnerable builder; control over a separate mirror, proxy, or transport position remains a prerequisite. FIRST defines UI:R as human participation beyond the attacker, while a scheduled pipeline still creates an operational window when it fetches. AC:H reflects object selection, delivery position, and timing conditions.
3.1 TLS, mirror authority, and cache policy shape the delivery surface
HTTPS, certificate validation, controlled DNS, approved-repository allowlists, and least-privilege proxy administration reduce opportunities for transport modification. If an origin, mirror, or legitimately authorized proxy is compromised, an encrypted connection can still deliver data inconsistent with authenticated control metadata, so in-format verification remains active. A redirect to another host also requires renewed review of credential forwarding, trust policy, and log ownership.
Shared cache and fallback change investigation. Cache should keep index snapshot, architecture, and APK object as one reconstructable set. If a first source returns an integrity error, later success from another source cannot erase the earlier object. Preserve source, package version, job, index snapshot, and object digest for isolation and origin review.
Multi-repository configuration eventually resolves to one concrete RepositoryPackage and URL. A configuration list is insufficient incident evidence; preserve the repository, mirror or proxy, architecture, and time actually selected by the solver. Consistency on amd64 cannot sign for an arm64 object, and a rolling index that is healthy today cannot substitute for its historical snapshot.
3.2 The confirmed primitive is package-file substitution; actual builds determine downstream impact
The data member carries executables, libraries, configuration, certificates, scripts, static assets, permissions, and link targets. The old getter could hand a replacement member to rootfs installation; public sources support that core capability. Preserving control clears the first gate, so the delivery does not require the repository signing private key or a SHA-1 collision.
Later execution, credential access, compiler influence, image publication, and runtime deployment depend on package purpose, guest privilege, build steps, and release action. Build success, registry push, deployment, and execution are separate states supported respectively by job records, provenance, registry audit, and runtime evidence. Public conclusions should stop at the state the evidence reaches.
apko installs packages directly into a target rootfs. In melange v0.56.3, buildGuest() lines 299–390 use apko to lock dependencies, obtain repository indexes, and build the build guest; Test.BuildGuest() lines 139–195 use apko for the test guest. A substituted compiler or generator may affect later output even when the tool itself is absent from the final image. melange usage limited to parsing YAML, producing metadata, or never creating a guest falls outside that same reachable path.
Alerting should distinguish four states: affected code in inventory, a mismatch rejected by fixed code, a preserved historical object confirmed inconsistent, and downstream execution or publication confirmed. Version presence starts investigation. A second-gate error is a high-value supply-chain signal. Merging the two states hides the actual anomaly beneath routine inventory findings.
4 apko carries the root repair; melange receives it through dependency upgrade
apko commit 8d34c756b1acdec0d18c82247f900a54255500f5 merged the second gate on April 28, 2026, and v1.2.9 was released that day. The patch keeps APK v2 unchanged and requires no new producer signature. It consumes the existing datahash and PackageHash. The v1.2.9 tag points to the later commit 312a1507941c846eadc2ff22d1e2e1f7d82bebe7, so root-fix commit and release tag serve distinct evidentiary roles.
melange commit 9852e87fe4de7e2ca43d5029efd0948b2db5cae1 moves chainguard.dev/apko from 1.2.7 to 1.2.9, and v0.50.4 contains that change. The relevant source retains the same mechanism across those tags: APK producer (v0.50.3, v0.50.4), index (before, after), signer (before, after), and tar writer (before, after) did not change for this repair. The producer already emitted the data digest; the consumer dependency contains the security change.
In the July 26 review, release-target apko v1.2.25 resolves to tag commit 34cdf14533a0f0d7874cce7a7e514f937ffd7386, melange v0.56.3 resolves to 9ebf436f4e63634008f93e5676517f12a411d840, and that release's go.mod lines 1–7 require apko v1.2.25. These are the release targets at review time; deployment rechecks official versions and support status.
4.1 Verify the executing module and equivalent patch beyond a version string
Official distributions support fast screening by product version. Internal builds also require go version -m, SBOM, build provenance, binary SHA-256, and source commit. A replace directive, vendored copy, fork, or monorepo copy can make a newer product version carry an old getter, while an older semantic version can contain an equivalent backport.
An equivalent backport is accepted against the same success condition: after the first gate, read and decode the data expectation from authenticated control; close and error when the second gate fails; permit new cache, return, and installation only after success. An exception record should carry pinned source ranges, build record, binary identity, a valid-package positive control, and both mismatch regressions.
A go.sum change records different module content but cannot establish what the final binary linked after build tags, graph pruning, vendoring, and replacements. The release ticket should join source module graph, build command, module information extracted from the artifact, and binary digest.
4.2 Decisive dates and release-artifact verification
apko 1.2.9 and melange 0.50.4 were both released on April 28, 2026. The maintainer GHSA in the melange repository became public on June 3. GitHub Advisory Database published its reviewed global record at 21:43:05 UTC on July 10, corresponding to 05:43:05 on July 11 in Shanghai. Fixed artifacts preceded the global record by more than two months, so historical exposure follows the tool and object evidence of each build.
Release pages provide architecture-specific Linux amd64 and arm64 archives, checksum manifests, signatures, and certificates. Verify the downloaded archive against the publisher manifest, validate signature or certificate, inspect the extracted binary's module, and bind the result to the internal tool-image digest. Each architecture has its own archive digest; one platform's value cannot authenticate another, and an archive digest cannot replace module inspection.
At the pinned research snapshot, GitHub associated the advisory with CVE-2026-54174, while a complete public CVE Services record and useful NVD entry were still absent. The maintainer GHSA, reviewed GHSA, and pinned source support mechanism, affected range, score, and repair. Registration status explains database coverage only.
5 Historical review reconstructs the index, object, and build result seen at the time
Fixed code governs future new fetches. Historical builds still require an answer about bytes actually received. A healthy origin today describes current state, while an affected-version finding describes code exposure. Investigation should join a named builder, one index selection, one APK object, and a concrete OCI output into a recomputable object path.
5.1 Fix executing code and delivery view first, then rerun both gates
Inventory developer workstations, CI runners, build services, release containers, reusable actions, and internal tool images. Record apko or melange version, binary SHA-256, embedded modules, image digest, build time, and owner for each location. Job metadata and execution-image history can restore short-lived runners after their local storage disappears.
Recover the effective repository URL, mirror order, architecture, index-signing key, proxy, lock, environment overrides, and command-line arguments. Preserve contemporary APKINDEX with its signature, exact APK bytes, proxy hit state, and whole-object SHA-256 for high-value builds. Redact credentials from forensic copies while retaining host, path, snapshot, and object identity.
Authenticate the index snapshot for each preserved object, then rerun the first and second gates from Chapter 1. Isolate the original and stop relying on the package when either relation fails. After both pass, compare paths, content hashes, modes, owners, and links from data with rootfs, SBOM, OCI layer, config, manifest, signature, and provenance.
SHA-256 over the complete consecutive .apk byte stream identifies the same download across object storage, proxies, and runners. Its object differs from the control digest and the data-member digest. A whole-object change locates change somewhere in the complete stream; the first and second gates establish which publication relationship holds.
5.2 Three conclusion classes drive retention, rebuild, and replacement
The first class used a fixed getter, has verifiable tool origin, and passes both gates. The second ran affected code but retains objects and output sufficient for consistency review. The third lacks executing version, historical object, or source evidence. The third enters a priority rebuild queue and is recorded as “unable to recompute,” without being promoted to confirmed substitution.
Image reconstruction should fix repository snapshot, toolchain, architecture, locale, umask, compressor, and filesystem semantics. If the complete OCI digest differs, explain package versions, file content, tar ordering, time metadata, and layer-production steps. Unexplained executable, library, configuration, permission, and link changes receive highest priority.
A build tool may execute at an intermediate stage and later disappear, while multiple packages may overwrite the same path. Investigation needs installation order, replaces relationships, build commands, and output provenance. Final SBOM or rootfs alone can miss intermediate influence. Review each platform of a multi-architecture manifest before deciding whether to replace the aggregate tag.
Closure records the same facts for every high-value artifact: getter that ran, index snapshot, actual APK, results of both gates, file and image differences, publication and deployment state, replacement digest, and old-object withdrawal. A missing field lowers conclusion confidence and cannot be supplied by a CVE scanner label.
6 Clean reconstruction and old-object withdrawal close the incident together
A binary upgrade changes the next execution. Complete closure preserves evidence, retires old cache, pins input, rebuilds from an empty workspace, explains differences, replaces published artifacts, and prevents old tools and digests from returning to the release surface. One change ticket should track these connected transitions across build, registry, and consumer.
6.1 Move from input freeze to replacement artifacts
- Freeze new publication on affected paths, preserve indexes, APKs, caches, logs, and artifacts needed for investigation, and isolate old cache and unknown-origin objects.
- Deploy fixed apko and melange, verify module and binary identity, and start with empty process cache, empty disk cache, and a clean workspace.
- Select an authenticated and preferably immutable repository snapshot, recording resolved versions, mirror or proxy position, and object digests per architecture.
- Run valid, control-mismatch, and data-mismatch qualification; rebuild high-value guests and OCI images afterward, discarding the complete workspace on failure.
- Explain package, file, layer, and manifest differences; issue replacement digests and withdraw old objects from replicated registries, floating tags, multi-architecture manifests, downstream pins, and offline copies.
Rollback policy preserves the two-gate safety property. A compatibility fault in the new release can move to an internal build carrying an equivalent patch or pause remote retrieval. Returning to an affected getter restores the same success branch. Build policy should encode the minimum safe module and binary allowlist in the release gate.
Replacing a floating tag does not remove a digest already pulled by a consumer. The release team needs replacement digests, a consumer inventory, and a verification method. Unreachable offline environments and long-lived pins remain open objects after the central registry update.
6.2 Long-term gates observe integrity, build, and publication separately
CI continuously runs one valid positive control and two independent mismatch negative controls. The release gate checks the tool-image digest, apko module in the SBOM, source commit, and complete provenance before granting production signing and registry-push authority. Every integrity error blocks the current job from promotion and retains failed-object and source identity.
Monitoring counts control mismatch, data mismatch, encoding error, parse error, and download error separately. Fields should include repository host, package name and version, architecture, index snapshot, failure class, builder binary, job, and time. Correlating a data mismatch with the same object on other runners, mirrors, and regions distinguishes a delivery-node event from an upstream publication fault.
Repository operators can recompute both gates against sampled snapshots, while builders execute the same contract from the consumer side. Retention keeps index and APK within the same investigative window and preserves failed jobs alongside successful release logs. A digest becomes a supply-chain control when the consumer compares authenticated metadata with the actual object it describes and blocks the object on failure before the next authorization step.
Research record
7Evidence, objects, and sources
The material below preserves the identifiers and references used in this report.
7.1Research objects
Products, actors, techniques, affected objects, and control points discussed in the report.
Incomplete APK data-member integrity enforcement in apko and melange
Affected apko range; fixed in 1.2.9
Affected melange range; 0.50.4 resolves to fixed apko
Default deployment target as of July 26, 2026; recheck at deployment
Default deployment target as of July 26, 2026; its go.mod requires apko 1.2.25
apko root-fix commit
Authenticated control declaration must equal the observed data-member digest
7.2Event chronology
- apko 1.2.9 released
apko merged the data-digest comparison and released 1.2.9; melange 0.50.4 upgraded to the fixed dependency the same day.
- Maintainer advisory published
The melange repository published GHSA-fpg8-7664-jc5q.
- Reviewed global advisory published
GitHub Advisory Database published the reviewed record at 21:43 UTC, corresponding to July 11 at 05:43 in Shanghai.
- Pinned source review completed
Production, index, expansion, retrieval, pre-publication gate, installation, and release-object paths were reviewed against fixed commits.
7.3Sources and material
- melange maintainer advisory GHSA-fpg8-7664-jc5qhttps://github.com/chainguard-dev/melange/security/advisories/GHSA-fpg8-7664-jc5q
- GitHub Advisory Database reviewed recordhttps://github.com/advisories/GHSA-fpg8-7664-jc5q
- GitHub Advisory Database API recordhttps://api.github.com/advisories/GHSA-fpg8-7664-jc5q
- CVE Services identifier statushttps://cveawg.mitre.org/api/cve-id/CVE-2026-54174
- CVE Services public record lookuphttps://cveawg.mitre.org/api/cve/CVE-2026-54174
- NVD CVE API lookuphttps://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-54174
- FIRST CVSS v3.1 specificationhttps://www.first.org/cvss/v3-1/specification-document
- MITRE ATT&CK T1195.002https://attack.mitre.org/techniques/T1195/002/
- apko fix commit 8d34c756https://github.com/chainguard-dev/apko/commit/8d34c756b1acdec0d18c82247f900a54255500f5
- apko PR #2206https://github.com/chainguard-dev/apko/pull/2206
- apko 1.2.9 releasehttps://github.com/chainguard-dev/apko/releases/tag/v1.2.9
- apko 1.2.25 release target at reviewhttps://github.com/chainguard-dev/apko/releases/tag/v1.2.25
- Pinned apko v1.2.8 to v1.2.9 comparisonhttps://github.com/chainguard-dev/apko/compare/v1.2.8...v1.2.9
- Pre-fix package_getter.go lines 129–183https://github.com/chainguard-dev/apko/blob/a7f10d8972fa035714387d9621745397a2f4135c/pkg/apk/apk/package_getter.go#L129-L183
- Fixed package_getter.go lines 129–208https://github.com/chainguard-dev/apko/blob/8d34c756b1acdec0d18c82247f900a54255500f5/pkg/apk/apk/package_getter.go#L129-L208
- apko APK expansion and digest calculationhttps://github.com/chainguard-dev/apko/blob/8d34c756b1acdec0d18c82247f900a54255500f5/pkg/apk/expandapk/expandapk.go
- apko hash-verification regression testshttps://github.com/chainguard-dev/apko/blob/8d34c756b1acdec0d18c82247f900a54255500f5/pkg/apk/apk/package_getter_test.go
- melange apko dependency-fix commithttps://github.com/chainguard-dev/melange/commit/9852e87fe4de7e2ca43d5029efd0948b2db5cae1
- melange PR #2506https://github.com/chainguard-dev/melange/pull/2506
- melange 0.50.4 releasehttps://github.com/chainguard-dev/melange/releases/tag/v0.50.4
- melange 0.56.3 release target at reviewhttps://github.com/chainguard-dev/melange/releases/tag/v0.56.3
- Pinned melange v0.50.3 to v0.50.4 comparisonhttps://github.com/chainguard-dev/melange/compare/v0.50.3...v0.50.4
- melange buildGuest apko consumption pathhttps://github.com/chainguard-dev/melange/blob/v0.50.3/pkg/build/build.go
- melange APK production implementationhttps://github.com/chainguard-dev/melange/blob/2582b68ddc8ca21b08bf7b244a2ff60bcbcee88f/pkg/build/package.go
- melange APK signing implementationhttps://github.com/chainguard-dev/melange/blob/2582b68ddc8ca21b08bf7b244a2ff60bcbcee88f/pkg/sign/apk.go
- apk-tools official APK v2 format documentationhttps://gitlab.alpinelinux.org/alpine/apk-tools/-/blob/90b974fd8510fbc2b3d6adde311ad1ba8754c728/doc/apk-v2.5.scd
- Alpine package-format overviewhttps://wiki.alpinelinux.org/wiki/Alpine_package_format
- Chainguard apko and melange toolchain overviewhttps://edu.chainguard.dev/open-source/build-tools/apko/overview/