cmake/Tests/RunCMake/CommandLineTar/path-absolute.cmake
Leslie P. Polzer 03f19aa4ea cmSystemTools: Fix path traversal vulnerability in archive extraction
Add security flags to libarchive extraction to prevent path traversal
(Zip Slip) and absolute path attacks:

- ARCHIVE_EXTRACT_SECURE_NODOTDOT: Block ".." path components
- ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS: Block absolute paths
- ARCHIVE_EXTRACT_SECURE_SYMLINKS: Block symlinks escaping extract dir

This hardens both `cmake -E tar` and `file(ARCHIVE_EXTRACT)` against
malicious archives that attempt to write files outside the intended
extraction directory.
2026-01-16 08:54:07 -05:00

58 lines
1.7 KiB
CMake

# Test that absolute path attacks are blocked during extraction
set(EXTRACT_DIR "${CMAKE_CURRENT_BINARY_DIR}/extract_dir_abs")
# Use an absolute path within the build tree (but outside EXTRACT_DIR)
set(MALICIOUS_FILE "${CMAKE_CURRENT_BINARY_DIR}/SHOULD_NOT_EXIST_ABS.txt")
# Clean up
file(REMOVE_RECURSE "${EXTRACT_DIR}")
file(REMOVE "${MALICIOUS_FILE}")
file(MAKE_DIRECTORY "${EXTRACT_DIR}")
# Create a malicious tar archive using Python
# The archive contains a file with an absolute path
set(MALICIOUS_TAR "${CMAKE_CURRENT_BINARY_DIR}/malicious_abs.tar")
file(REMOVE "${MALICIOUS_TAR}")
execute_process(
COMMAND "${Python_EXECUTABLE}" -c [==[
import sys
import tarfile
import io
# Create a tar archive in memory
tar_data = io.BytesIO()
with tarfile.open(fileobj=tar_data, mode='w') as tar:
# Add a file with absolute path
data = b'malicious content'
info = tarfile.TarInfo(name=sys.argv[2])
info.size = len(data)
tar.addfile(info, io.BytesIO(data))
# Write to file
with open(sys.argv[1], 'wb') as f:
f.write(tar_data.getvalue())
]==] "${MALICIOUS_TAR}" "${MALICIOUS_FILE}"
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to create malicious tar archive")
endif()
# Try to extract the malicious archive
execute_process(
COMMAND "${CMAKE_COMMAND}" -E tar xf "${MALICIOUS_TAR}"
WORKING_DIRECTORY "${EXTRACT_DIR}"
RESULT_VARIABLE extract_result
)
# The file should not exist at the absolute path
if(EXISTS "${MALICIOUS_FILE}")
message(FATAL_ERROR "PATH TRAVERSAL VULNERABILITY: File was created outside extraction directory!")
endif()
if(extract_result EQUAL 0)
message(FATAL_ERROR "Extraction of malicious path did not fail!")
endif()