CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-28407
6.9

Malcontent Logic Error: Nested Archive Deletion Allows Detection Bypass

Alon Barad
Alon Barad
Software Engineer

Feb 28, 2026·5 min read·4 visits

PoC Available

Executive Summary (TL;DR)

Logic error in malcontent < 1.21.0 deletes nested archives even if extraction fails, allowing malformed malicious files to bypass scanning.

A logic vulnerability in the `malcontent` supply chain security tool allows attackers to bypass detection engines. The issue resides in the handling of nested archives (e.g., a `.tar` inside a `.zip`). When the scanner attempts to extract a nested archive and fails due to malformed headers or corruption, it unconditionally deletes the source archive file. This removal occurs before the content scanning phase, effectively hiding the malicious payload from analysis. Attackers can exploit this by crafting archives that fail extraction but contain malicious signatures in their raw bytes.

Vulnerability Overview

malcontent is an open-source security tool developed by Chainguard to detect supply-chain compromises. It employs a combination of context analysis, differential analysis, and YARA signatures to identify malicious code within software artifacts. A core feature of the tool is its ability to recursively unpack nested archives to inspect their contents.

The vulnerability, identified as CVE-2026-28407, affects the extraction logic for these nested archives. In affected versions (< 1.21.0), the scanner enforces a cleanup policy that is too aggressive. When malcontent encounters a nested archive, it attempts to extract it to a temporary directory for analysis. Crucially, the code was designed to remove the temporary archive file after the extraction attempt to save space. However, this removal was performed unconditionally, regardless of whether the extraction succeeded or failed.

This behavior creates a race-condition-like logic flaw where the artifact containing potential malware is deleted from the disk specifically because it failed to unpack. Since the subsequent scanning phases (YARA and heuristics) operate on the files remaining on the disk, the malicious artifact simply vanishes from the scanner's view, resulting in a false negative report.

Root Cause Analysis

The root cause is an improper handling of exceptional conditions (CWE-703) within the extractNestedArchive function in pkg/archive/archive.go (and related extraction logic). The function is responsible for orchestrating the decompression of files found within other files.

The logic flow in vulnerable versions was as follows:

  1. Identify a file as an archive based on MIME type or extension.
  2. Call the extraction routine (e.g., tar, zip, gzip).
  3. Check the error return from the extraction routine.
  4. If an error occurred, log it (often at debug level) and continue execution.
  5. Unconditionally call os.Remove(archivePath) to delete the nested archive file.

By deleting the file even after a failure, the code assumes that if extraction failed, the file is either useless or benign garbage. This assumption is incorrect in a security context. A file can be a valid executable or contain a valid YARA signature while simultaneously having a corrupted archive header that causes standard extraction libraries to error out. The scanner relies on inspecting the extracted content OR the raw content. By deleting the raw content after failing to produce extracted content, the scanner inspects nothing.

Code Analysis

The vulnerability is evident in the patch diff provided by the maintainers. The fix involves wrapping the deletion logic in a conditional block that checks if the extraction error was nil.

Vulnerable Logic

In the original code, the cleanup os.Remove runs regardless of the err state from the extraction function.

// ... inside the extraction loop ...
err := extract(f, d)
if err != nil {
    // Error is logged, but control flow continues
    logger.Debugf("ignoring extraction error for %s: %s", f, err.Error())
}
 
// CRITICAL FLAW: The source file 'fullPath' is deleted even if extraction failed.
// This removes the evidence before the scanner can look at it.
if err := os.Remove(fullPath); err != nil {
    return fmt.Errorf("failed to remove archive file: %w", err)
}

Patched Logic

The fix introduced in version 1.21.0 explicitly preserves the file if extraction fails. This allows the scanner to fall back to scanning the raw file itself.

// ... inside the extraction loop ...
err := extract(f, d)
// ... error logging ...
 
// FIX: Only attempt to remove the archive file if we successfully extracted it.
// If 'err' is not nil, the file remains on disk for the scanner to inspect.
if err == nil {
    if err := os.Remove(fullPath); err != nil {
        return fmt.Errorf("failed to remove archive file: %w", err)
    }
}

Exploitation Methodology

Exploiting this vulnerability requires an attacker to craft a "broken" archive that is technically invalid enough to fail the specific Go extraction library used by malcontent, yet still contains the malicious payload in its byte stream.

Attack Scenario

  1. Preparation: The attacker generates a malicious payload (e.g., a reverse shell script or a binary matching a known signature).
  2. Containerization: This payload is placed inside a nested archive structure. For example, payload.bin is put inside inner.tar.gz.
  3. Corruption: The attacker intentionally corrupts the headers of inner.tar.gz or truncates the footer. The goal is to ensure that gzip or tar readers return an error (e.g., unexpected EOF or invalid header) immediately upon processing, or partially through processing.
  4. Delivery: This corrupted inner.tar.gz is packed inside a valid outer.zip.

Execution Flow

When malcontent scans outer.zip, it successfully extracts inner.tar.gz. It then identifies inner.tar.gz as an archive and attempts to extract it. The extraction fails due to the corruption. The vulnerable code catches the error, logs "ignoring extraction error", and immediately deletes inner.tar.gz.

The scanner then iterates over the directory. Since inner.tar.gz was deleted and no files were extracted from it, the directory appears empty or benign. The malicious payload, which existed in the raw bytes of inner.tar.gz, is gone.

Impact Assessment

The primary impact of CVE-2026-28407 is a Security Control Bypass. malcontent is relied upon to gate software supply chains, often running in CI/CD pipelines to block malicious dependencies or artifacts.

By successfully bypassing this check, an attacker can introduce malware into a trusted environment. While the vulnerability does not directly grant remote code execution (RCE) on the scanning infrastructure itself, it neutralizes the scanner's ability to protect downstream systems.

Severity Metrics:

  • CVSS v4.0: 6.9 (Medium) - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N. The attack vector is Network, and complexity is Low. The impact is framed as Low Integrity impact because the integrity of the scan results is compromised.
  • Scope: This affects any pipeline relying solely on malcontent version < 1.21.0 for artifact validation.

Official Patches

chainguard-devGitHub Commit: Fix for nested archive deletion logic
chainguard-devOfficial GHSA Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
6.9/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N

Affected Systems

malcontent < 1.21.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
malcontent
chainguard-dev
< 1.21.01.21.0
AttributeDetail
CWE IDCWE-703
CVSS v4.06.9 (Medium)
Attack VectorNetwork
VendorChainguard
Exploit StatusPOC Available
Patch StatusReleased (v1.21.0)

MITRE ATT&CK Mapping

T1562.006Indicator Blocking
Defense Evasion
T1027Obfuscated Files or Information
Defense Evasion
CWE-703
Improper Check or Handling of Exceptional Conditions

Improper Check or Handling of Exceptional Conditions

Vulnerability Timeline

Fix committed to main branch
2026-02-17
GitHub Security Advisory published
2026-02-27
CVE-2026-28407 assigned and published
2026-02-27

References & Sources

  • [1]GHSA-945p-3jhm-6rcp
  • [2]NVD Entry for CVE-2026-28407

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.