VYPR
Critical severity9.1NVD Advisory· Published Mar 27, 2024· Updated Apr 15, 2026

CVE-2024-28335

CVE-2024-28335

Description

Lektor before 3.3.11 does not sanitize DB path traversal. Thus, shell commands might be executed via a file that is added to the templates directory, if the victim's web browser accesses an untrusted website that uses JavaScript to send requests to localhost port 5000, and the web browser is running on the same machine as the "lektor server" command.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
LektorPyPI
< 3.3.113.3.11
LektorPyPI
>= 3.4.0b1, < 3.4.0b113.4.0b11

Patches

2
7393d87bd354

Sanitize DB path traversal (#1179)

https://github.com/lektor/lektorJeff DairikiFeb 27, 2024via ghsa
4 files changed · +33 2
  • lektor/editor.py+13 0 modified
    @@ -16,8 +16,10 @@
     from lektor.constants import PRIMARY_ALT
     from lektor.metaformat import serialize
     from lektor.utils import atomic_open
    +from lektor.utils import cleanup_path
     from lektor.utils import increment_filename
     from lektor.utils import is_valid_id
    +from lektor.utils import parse_path
     from lektor.utils import secure_filename
     
     
    @@ -33,8 +35,19 @@ class BadDelete(BadEdit):
         pass
     
     
    +def _is_valid_path(path: str) -> bool:
    +    split_path = path.strip("/").split("/")
    +    if split_path == [""]:
    +        split_path = []
    +    return parse_path(path) == split_path
    +
    +
     def make_editor_session(pad, path, is_attachment=None, alt=PRIMARY_ALT, datamodel=None):
         """Creates an editor session for the given path object."""
    +    if not _is_valid_path(path):
    +        raise BadEdit("Invalid path")
    +    path = cleanup_path(path)
    +
         if alt != PRIMARY_ALT and not pad.db.config.is_valid_alternative(alt):
             raise BadEdit("Attempted to edit an invalid alternative (%s)" % alt)
     
    
  • lektor/utils.py+3 2 modified
    @@ -149,10 +149,11 @@ def is_path_child_of(a, b, strict=True):
     
     
     def untrusted_to_os_path(path):
    -    path = path.strip("/").replace("/", os.path.sep)
         if not isinstance(path, str):
             path = path.decode(fs_enc, "replace")
    -    return path
    +    clean_path = cleanup_path(path)
    +    assert clean_path.startswith("/")
    +    return clean_path[1:].replace("/", os.path.sep)
     
     
     def is_path(path):
    
  • tests/test_editor.py+1 0 modified
    @@ -43,6 +43,7 @@ def test_make_editor_session(pad, path, kwargs, expect):
                 "conflicting",
                 marks=pytest.mark.xfail(reason="buglet that should be fixed"),
             ),
    +        ("/../../templates", {}, "Invalid path"),
         ],
     )
     def test_make_editor_session_raises_bad_edit(pad, path, kwargs, expect):
    
  • tests/test_utils.py+16 0 modified
    @@ -1,3 +1,4 @@
    +import os
     import warnings
     from contextlib import contextmanager
     from dataclasses import dataclass
    @@ -16,6 +17,7 @@
     from lektor.utils import secure_url
     from lektor.utils import slugify
     from lektor.utils import unique_everseen
    +from lektor.utils import untrusted_to_os_path
     from lektor.utils import Url
     
     
    @@ -336,3 +338,17 @@ def _warning_line(warning: warnings.WarningMessage) -> str:
         """Get the text of the line for which warning was issued."""
         with open(warning.filename, encoding="utf-8") as fp:
             return next(islice(fp, warning.lineno - 1, None), None)
    +
    +
    +@pytest.mark.parametrize(
    +    "db_path, expected",
    +    [
    +        ("a/b", "a/b"),
    +        ("/a/b", "a/b"),
    +        ("a/b/", "a/b"),
    +        ("/../../a", "a"),
    +    ],
    +)
    +def test_untrusted_to_os_path(db_path, expected):
    +    os_path = untrusted_to_os_path(db_path)
    +    assert os_path.split(os.sep) == expected.split("/")
    

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

11

News mentions

0

No linked articles in our index yet.