From a696d5ba93270d5954f98e7cab5ddca8a02c1e32 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Fri, 21 Nov 2025 17:07:53 +0000 Subject: [PATCH] varLib: only use the basename(vf.filename) Fontmake already does that since the beginning: https://github.com/googlefonts/fontmake/blob/35e9e5dbdf2130a04c54688bb1bdbcfdb4b5fc67/Lib/fontmake/font_project.py#L438 it's safer to disallow path traversal as it may lead to abritrary file write vulnerability, see https://github.com/fonttools/fonttools/security/advisories/GHSA-768j-98cg-p3fv --- Doc/source/designspaceLib/xml.rst | 5 +++++ Lib/fontTools/designspaceLib/__init__.py | 5 +++++ Lib/fontTools/varLib/__init__.py | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Doc/source/designspaceLib/xml.rst b/Doc/source/designspaceLib/xml.rst index f5645b8ca4..6896f49e25 100644 --- a/Doc/source/designspaceLib/xml.rst +++ b/Doc/source/designspaceLib/xml.rst @@ -752,6 +752,11 @@ The ```` element contains one or more ```` elemen `.ttf`) and the build tools can replace that extension with another (e.g. `.otf` or `.woff2`) as needed. + .. note:: + This is intended to be a simple filename (basename or stem) only, not + an absolute or relative path. Build tools will only use the basename + component and ignore any directory separators for security reasons. + .. rubric:: Example .. code:: xml diff --git a/Lib/fontTools/designspaceLib/__init__.py b/Lib/fontTools/designspaceLib/__init__.py index 661f3405da..0996e7b69e 100644 --- a/Lib/fontTools/designspaceLib/__init__.py +++ b/Lib/fontTools/designspaceLib/__init__.py @@ -1323,6 +1323,11 @@ def __init__(self, *, name, filename=None, axisSubsets=None, lib=None): in the document**. The file may or may not exist. If not specified, the :attr:`name` will be used as a basename for the file. + + .. note:: + This is intended to be a simple filename (basename or stem) only. + Build tools will only use the basename component and ignore any + directory separators for security reasons. """ self.axisSubsets: List[ Union[RangeAxisSubsetDescriptor, ValueAxisSubsetDescriptor] diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py index fd0875567c..c19bd15158 100644 --- a/Lib/fontTools/varLib/__init__.py +++ b/Lib/fontTools/varLib/__init__.py @@ -1562,7 +1562,11 @@ def main(args=None): vf_name_to_output_path[vfs_to_build[0].name] = options.outfile else: for vf in vfs_to_build: - filename = vf.filename if vf.filename is not None else vf.name + ".{ext}" + if vf.filename is not None: + # Only use basename to prevent path traversal attacks + filename = os.path.basename(vf.filename) + else: + filename = vf.name + ".{ext}" vf_name_to_output_path[vf.name] = os.path.join(output_dir, filename) finder = MasterFinder(options.master_finder)