Skip to content

Commit 27fe69e

Browse files
committed
libpsl: fix to not leak build-time PSL db filename into the binaries [ci skip]
To prevent libpsl trying to load it a runtime, insecurely, from uncontrolled, potentially world-writable disk locations, and overriding the embedded PSL database with it. Fix by patching the code generated by the Python script shipping with libpsl. Also verify that the filename is not present in the C source. Explanation: The libpsl script responsible for generating the embedded PSL data is also including the local, built-time PSL data filename in the generated C source. In case of curl-for-win this filename is a relative one. When curl/libcurl calls `psl_latest()` to load the list, libpsl is accessing this filename on disk, and if there is such file that's newer than the embedded PSL data, it loads it. This filename in practice is a relative one to the current working directory. It means that an attacker can place an empty or doctored, new PSL database on disk and override the embedded one with it. Probably something to be fixed in upstream libpsl, possibly by allowing to customize the filename that is being hard-coded (including to an empty filename to prevent loading it), and/or allowing to disable the dynamic loading feature fully. (The latter would also fix the `stat()` use issue on Windows and mingw-w64 v13.)
1 parent 153f658 commit 27fe69e

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

libpsl.sh

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,32 @@ _VER="$1"
2323
# Build manually
2424

2525
# require the psl package, always
26-
[ -f 'suffixes_dafsa.h' ] || python3 'src/psl-make-dafsa' --output-format=cxx+ "../psl/${_PSL}" 'suffixes_dafsa.h'
26+
if [ ! -f 'suffixes_dafsa.h' ]; then
27+
pslfile="../psl/${_PSL}"
28+
gencsrc='suffixes_dafsa.h'
29+
python3 'src/psl-make-dafsa' --output-format=cxx+ "${pslfile}" "${gencsrc}"
30+
# The generator above is including the local PDL filename in the output.
31+
# libpsl is then making an attemp to load this filename at runtime as-is
32+
# and loading its content if its timestamp is newer than the embedded one.
33+
# This is terrible idea in many use cases, including this one, because:
34+
# - the filename is relative one.
35+
# - this is loaded on the end user's machine, relative to their current
36+
# working directory.
37+
# - which is by good chance world-writable, and for sure without any
38+
# guarantees for protection.
39+
# - there is no universal location on disks that is not world-writable.
40+
# - leaks this internal filename into the final binary.
41+
# Similar case to OpenSSL configurations and CA bundles loaded from
42+
# world-writable, or arbitrary places on disk (such as PATH), on Windows.
43+
# To avoid these issues, strip the filename from the output to avoid
44+
# loading it at runtime:
45+
sed -i.bak -E 's/(_psl_filename\[\]) *=.+/\1 = "";/g' "${gencsrc}"
46+
# Verify and abort if the filename is still found in the file
47+
if grep -a -F "${pslfile}" "${gencsrc}"; then
48+
echo "! Error: Our local PSL database filename is leaking into the libpsl code."
49+
exit 1
50+
fi
51+
fi
2752

2853
mkdir -p "${_BLDDIR}"
2954
(

0 commit comments

Comments
 (0)