VYPR
High severity8.7GHSA Advisory· Published May 12, 2026· Updated May 13, 2026

CVE-2026-44307

CVE-2026-44307

Description

Mako is a template library written in Python. Prior to 1.3.12, on Windows, a URI using backslash traversal (e.g. \..\..\ secret.txt) bypasses the directory traversal check in Template.__init__ and the posixpath-based normalization in TemplateLookup.get_template(), allowing reads of files outside the configured template directory. This vulnerability is fixed in 1.3.12.

Affected products

1

Patches

1
72e10c573ca0

Fix path traversal via backslash URI on Windows in TemplateLookup

https://github.com/sqlalchemy/makoMike BayerApr 28, 2026via ghsa
4 files changed · +52 2
  • doc/build/unreleased/435.rst+10 0 added
    @@ -0,0 +1,10 @@
    +.. change::
    +    :tags: bug, template
    +    :tickets: 435
    +
    +    Fixed issue in :class:`.TemplateLookup` where a URI with backslash path
    +    separators (e.g. ``\..\secret.txt``) could bypass the directory traversal
    +    check on Windows, allowing reads of arbitrary files outside of the template
    +    directory.  This is an incomplete fix for :cve:`2026-41205`.  Backslash
    +    characters in URIs are now normalized to forward slashes before path
    +    resolution.
    
  • mako/lookup.py+1 1 modified
    @@ -241,7 +241,7 @@ def get_template(self, uri):
                 else:
                     return self._collection[uri]
             except KeyError as e:
    -            u = re.sub(r"^\/+", "", uri)
    +            u = re.sub(r"^\/+", "", uri.replace("\\", "/"))
                 for dir_ in self.directories:
                     # make sure the path seperators are posix - os.altsep is empty
                     # on POSIX and cannot be used.
    
  • mako/template.py+1 1 modified
    @@ -259,7 +259,7 @@ def __init__(
                 self.module_id = "memory:" + hex(id(self))
                 self.uri = self.module_id
     
    -        u_norm = self.uri.lstrip("/")
    +        u_norm = self.uri.replace("\\", "/").lstrip("/")
             u_norm = os.path.normpath(u_norm)
             if u_norm.startswith(".."):
                 raise exceptions.TemplateLookupException(
    
  • test/test_lookup.py+40 0 modified
    @@ -168,6 +168,46 @@ def test_dont_accept_relative_outside_of_root_via_double_slash(self):
                     "///" + rel,
                 )
     
    +    def test_dont_accept_relative_outside_of_root_via_backslash(self):
    +        """test that backslash traversal URI can't bypass the
    +        path traversal check"""
    +        with tempfile.TemporaryDirectory() as base:
    +            tmpl_dir = os.path.join(base, "app", "templates")
    +            os.makedirs(tmpl_dir)
    +            with open(os.path.join(tmpl_dir, "index.html"), "w") as f:
    +                f.write("Hello")
    +
    +            secret = os.path.join(base, "secrets", "creds.txt")
    +            os.makedirs(os.path.dirname(secret))
    +            with open(secret, "w") as f:
    +                f.write("SECRET_KEY=supersecret123")
    +
    +            tl = lookup.TemplateLookup(directories=[tmpl_dir])
    +            rel = os.path.relpath(secret, tmpl_dir).replace("/", "\\")
    +
    +            assert_raises_message(
    +                exceptions.TemplateLookupException,
    +                "cannot be relative outside of the root path",
    +                tl.get_template,
    +                rel,
    +            )
    +
    +            # with leading backslash
    +            assert_raises_message(
    +                exceptions.TemplateLookupException,
    +                "cannot be relative outside of the root path",
    +                tl.get_template,
    +                "\\" + rel,
    +            )
    +
    +            # with leading forward slash
    +            assert_raises_message(
    +                exceptions.TemplateLookupException,
    +                "cannot be relative outside of the root path",
    +                tl.get_template,
    +                "/" + rel,
    +            )
    +
         def test_checking_against_bad_filetype(self):
             with tempfile.TemporaryDirectory() as tempdir:
                 tl = lookup.TemplateLookup(directories=[tempdir])
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.