apko verifies the APKINDEX signature but never compares downloaded .apk checksums against the signed index. An attacker controlling any mirror can silently substitute arbitrary packages into built OCI images.
Imagine you're ordering building supplies through a trusted contractor. The contractor verifies that the supply list came from the manufacturer — but never actually checks that the individual bricks, cement, and wood delivered match what's on that list. That's essentially what's happening with apko, a tool developers use to package software into containers.
Apko builds what's called container images, which are like pre-packaged digital environments that run applications. These images are built from smaller software packages. The tool does check that the master list of packages came from a legitimate source, but it skips a crucial step: verifying that each individual package hasn't been tampered with during download.
This creates an opening for attackers on a network. If someone intercepts your internet connection — at a coffee shop, airport, or even through a compromised network — they could swap in malicious packages. Apko would accept them without question. The fake packages would end up baked into container images that developers then use and share widely.
Who's actually at risk? Primarily software developers and companies that use apko to build applications. If they unknowingly create images with poisoned packages, those contaminated images could spread to customers and users. It's a supply chain attack, meaning the harm flows downstream through multiple layers of trust.
What can you do? First, if you develop software, check whether apko is part of your build process and update it when patches arrive. Second, organizations should review which tools they use to build container images and ensure they're kept current. Third, push your vendors and tool providers to be transparent about their verification processes — checksums should always be checked, no exceptions.
Want the full technical analysis? Click "Technical" above.
CVE-2026-42575 is a checksum-bypass vulnerability in apko, Chainguard's tool for building OCI container images from Alpine APK packages. The vulnerability exists in the package fetch pipeline: apko correctly verifies the GPG signature on APKINDEX.tar.gz — the signed package index — but never actually compares the checksum of each individually downloaded .apk file against the checksum recorded in that signed index. The result is a classic TOCTOU-style trust gap: the signed manifest is validated, but the artifacts it describes are not.
Any attacker positioned between apko and the package mirror — a compromised mirror, an HTTP (non-TLS) repository, a poisoned CDN cache — can serve a maliciously substituted .apk while the signed index remains untouched. The build completes without error. The resulting OCI image contains the attacker's payload.
Root cause:getPackageImpl() computes the downloaded package's checksum and retrieves the expected value via ChecksumString() but never invokes a comparison between the two, silently accepting any substituted package.
Affected Component
The vulnerability lives in apko's APK fetch layer, specifically in pkg/apk/impl/fetch.go (pre-patch path). The affected function is getPackageImpl(), called for every package resolved during image construction. All apko versions prior to 1.2.7 are affected. The vulnerability impacts any build pipeline using HTTP repositories or mirrors not exclusively controlled by the build operator — including CI/CD environments pulling from public Alpine mirrors.
Root Cause Analysis
The APK index verification flow is correct in isolation. apko fetches APKINDEX.tar.gz, verifies its GPG signature, and populates package metadata including the per-package SHA-256 checksum. The checksum is exposed via ChecksumString() on the parsed Package struct. The problem is that getPackageImpl() — the function responsible for fetching and accepting individual packages — computes the actual checksum of the downloaded bytes but never performs the comparison.
// pkg/apk/impl/fetch.go — VULNERABLE (pre-1.2.7)
// Reconstructed Go pseudocode as C for clarity
int getPackageImpl(Repository *repo, Package *pkg, io.Writer *w) {
// Step 1: fetch the .apk tarball from the mirror
resp, err = http_get(repo->url + "/" + pkg->Filename);
if (err != nil) return err;
// Step 2: wrap writer with hash computation
hasher = sha256.New();
teeReader = io.TeeReader(resp.Body, hasher);
// Step 3: stream package data to output
io_copy(w, teeReader);
// Step 4: retrieve what we computed
actualChecksum = hasher.Sum(nil);
// Step 5: retrieve what the *signed index* says it should be
expectedChecksum = pkg->ChecksumString(); // e.g. "Q1abc123..."
// BUG: actualChecksum and expectedChecksum are NEVER COMPARED.
// Both values are computed/retrieved and then discarded.
// Any .apk body served by the mirror is silently accepted.
return nil;
}
The ChecksumString() method returns the checksum field parsed directly from the signed APKINDEX. It is a Q1-prefixed base64-encoded SHA-1 hash (Alpine's legacy format) or a raw hex SHA-256, depending on index version. Either way, the value is available and correct — it just goes unused.
// Package struct — relevant fields
struct Package {
/* ... */
char *Name; // package name
char *Version; // package version string
char *Filename; // relative path, e.g. "x86_64/busybox-1.36.1-r0.apk"
uint8_t Checksum[32]; // SHA-256 from signed APKINDEX — NEVER CHECKED
/* ... */
};
// ChecksumString() returns hex encoding of Package.Checksum.
// Computed at parse time from the verified, signed index.
// Correct. Trustworthy. Ignored.
Exploitation Mechanics
The attack requires the adversary to control or influence responses from any HTTP-accessible APK mirror. HTTPS does not fully mitigate this if the mirror itself is compromised; the vulnerability is at the content integrity layer, not the transport layer.
EXPLOIT CHAIN:
1. Identify a target apko build pipeline using an HTTP mirror or a CDN-fronted
HTTPS mirror (e.g., dl-cdn.alpinelinux.org via a poisoned CDN PoP).
2. Obtain (do not tamper with) the legitimate APKINDEX.tar.gz and its GPG
signature. apko will verify this successfully — leave it untouched.
3. Identify a target package in the index, e.g.:
alpine-baselayout-3.4.3-r2.apk
Checksum: 9f3a1b2c... (recorded in signed index)
4. Craft a malicious replacement .apk:
- Valid APK tar structure (gzip'd tar with .PKGINFO, scripts, data)
- Arbitrary payload in /usr/bin/ or init scripts
- SHA-256 of this file != 9f3a1b2c... (mismatch is irrelevant)
5. Serve the malicious .apk in place of the legitimate one when apko's
HTTP client requests:
GET /alpine/v3.19/main/x86_64/alpine-baselayout-3.4.3-r2.apk
6. apko receives the malicious body, computes its SHA-256, retrieves the
expected checksum from the signed index — and discards both values.
No error is raised.
7. The malicious package is unpacked into the OCI image layer.
apko signs the resulting OCI image (e.g., with cosign), attesting
to an image that contains attacker-controlled content.
8. The poisoned image is pushed to a registry and consumed by downstream
workloads, Kubernetes pods, or CI runners.
The CVSS 7.5 rating reflects network-exploitable, no-authentication-required access with high impact on integrity of built artifacts. The attack is particularly severe in supply-chain contexts: apko is heavily used by Chainguard Images, meaning a successful attack poisons "hardened" base images that downstream users trust implicitly — and that carry valid cosign signatures from the build system.
Memory Layout
This is a logic vulnerability rather than a memory corruption bug, so the relevant "layout" is the data flow through the fetch pipeline — specifically how the two checksum values co-exist in the same stack frame without ever being compared.
STACK FRAME: getPackageImpl() — pre-patch
[ resp ] → HTTP response body (attacker-controlled)
[ hasher ] → sha256.Hash instance
[ teeReader ] → io.TeeReader(resp.Body, hasher)
[ actualSum ] → hasher.Sum(nil) ← computed from attacker data
|
| NO COMPARISON PERFORMED
|
[ expectedSum ] → pkg.ChecksumString() ← from signed APKINDEX
[ return nil ] ← function exits cleanly regardless of mismatch
TRUST BOUNDARY VIOLATION:
┌─────────────────────────────────┐
│ APKINDEX.tar.gz (GPG verified) │ ← integrity guaranteed
│ └─ checksum: 9f3a1b2c... │
└─────────────────────────────────┘
│
│ ← gap: checksum never linked to downloaded artifact
▼
┌─────────────────────────────────┐
│ .apk download (unverified) │ ← attacker substitutes here
│ └─ actual: deadbeef... │ ← silently accepted
└─────────────────────────────────┘
Patch Analysis
The fix in apko 1.2.7 is exactly what it should be: after computing the actual checksum of the downloaded body, compare it against the expected value from the signed index. If they differ, return an error and abort the build.
The fix is minimal and correct. Note that the checksum comparison must occur afterio.Copy completes — the hash finalizes only once all bytes have been consumed. The patch correctly positions the comparison at this point. The error message surfaces both actual and expected checksums, which aids forensic detection of active exploitation attempts in build logs.
Detection and Indicators
Prior to patching, there are no runtime indicators — the vulnerability produces no errors, no warnings, and no log output. Detection requires out-of-band verification.
For historical builds: Re-fetch each .apk from a trusted source and compare SHA-256 against the checksum in the APKINDEX your build used. If your build logs retain the resolved index snapshot, extract checksums with:
import tarfile, hashlib, base64
def verify_apk(apk_path: str, expected_checksum_b64: str) -> bool:
# Alpine Q1-prefix checksum: base64(sha1(control section))
# Full-package SHA256 stored as raw hex in newer indexes
with open(apk_path, "rb") as f:
data = f.read()
actual = hashlib.sha256(data).hexdigest()
# Compare against index-recorded value (hex or Q1-stripped b64)
expected = expected_checksum_b64.lstrip("Q1")
try:
expected_hex = base64.b64decode(expected + "==").hex()
except Exception:
expected_hex = expected_checksum_b64 # already hex
return actual == expected_hex
# Flag any mismatch as potential supply-chain substitution
Post-patch indicators of attempted exploitation: apko 1.2.7+ will emit a fatal error containing "checksum mismatch for package" with both the actual and expected hashes. Monitor build logs for this string. A mismatch in production should be treated as an active supply-chain attack and the mirror should be immediately quarantined and reported.
Remediation
Immediate: Upgrade apko to version 1.2.7 or later. This is the only complete fix.
Defense in depth:
Pin all APK repositories to HTTPS endpoints with certificate pinning where your infrastructure supports it. This raises the bar for CDN cache poisoning but does not substitute for content verification.
Use --repository-append only with fully trusted, internally mirrored repositories in high-assurance builds.
Rebuild any OCI images produced by affected apko versions from a known-good build environment and re-verify all image digests.
If using Chainguard Images (which are built with apko), check the Chainguard advisory for confirmation that production builds were not affected; Chainguard has indicated their production infrastructure was not compromised.
Integrate apk verify or an equivalent checksum audit step into post-build image scanning pipelines as a secondary control.