VYPR
High severity7.5NVD Advisory· Published May 27, 2026

CVE-2026-48544

CVE-2026-48544

Description

Taipy 4.1.1, fixed in commit 129fd40, contains a path traversal vulnerability in the ElementLibrary.get_resource() method in taipy/gui/extension/library.py that allows unauthenticated attackers to escape the intended module directory by exploiting an incomplete path containment check using str.startswith() without a trailing path separator. Attackers can send crafted GET requests with path traversal segments targeting a prefix-matching sibling directory on disk, bypassing the directory containment check because Flask's path converter and Werkzeug's WSGI layer preserve the traversal segments while the resolved path still satisfies the flawed startswith comparison, enabling unauthorized file access outside the intended library directory.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Taipy 4.1.1 contains a path traversal in ElementLibrary.get_resource() due to a flawed str.startswith() containment check, allowing unauthenticated attackers to read arbitrary files.

Vulnerability

CVE-2026-48544 is a path traversal vulnerability in Taipy 4.1.1, fixed in commit 129fd40. The flaw resides in the ElementLibrary.get_resource() method in taipy/gui/extension/library.py. The method uses str(file).startswith(str(base)) without a trailing path separator to verify that a resolved file path remains within the intended library module directory. This allows an attacker to escape the directory if a prefix-matching sibling directory exists on disk (e.g., mylib/ and mylib_secrets/ under the same parent). No authentication is required to exploit the issue [1][3].

Exploitation

An unauthenticated attacker can send a crafted GET request to the /taipy-extension/<library_name>/../<sibling_directory>/ endpoint. Flask's <path:path> converter preserves .. segments, and Werkzeug's WSGI layer does not collapse them. The Gui._serve_extension method splits on /, preserving the traversal, and passes the path to get_resource(), where (base / name).resolve() moves out of the intended directory. The flawed str.startswith check then incorrectly accepts the path because the resolved path still satisfies the prefix comparison without a trailing separator. Both literal ../ and URL-encoded %2E%2E forms can be used [1].

Impact

Successful exploitation allows the attacker to read arbitrary files from the server that are located in a sibling directory whose name shares a prefix with the legitimate library directory. This can lead to disclosure of sensitive information such as credentials, configuration files, or other confidential data—as demonstrated by reading a creds.txt file from a sibling directory. The attack is unauthenticated and requires no special privileges [1][3].

Mitigation

The vulnerability is fixed in commit 129fd40, which replaces the str.startswith check with pathlib.Path.is_relative_to() (available in Python 3.9+). The fix was merged via pull request #2871 and closes issue #2868. Users should update Taipy to a version containing this commit (e.g., by pulling the latest from the develop branch or applying the patch directly). No workarounds are documented if the patch cannot be applied. The CVE is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog as of publication date [2][4].

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Avaiga/Taipyreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: =4.1.1

Patches

1
129fd407ffca

is_relative_to is better than starts_with (#2871)

https://github.com/avaiga/taipyFred Lefévère-LaoideApr 30, 2026via nvd-ref
1 file changed · +1 1
  • taipy/gui/extension/library.py+1 1 modified
    @@ -371,7 +371,7 @@ def get_resource(self, name: str) -> Path:
             """  # noqa: E501
             base = self.__get_class_folder()
             file = (base / name).resolve()
    -        if str(file).startswith(str(base)) and file.exists():
    +        if file.is_relative_to(base) and file.exists():
                 return file
             else:
                 raise FileNotFoundError(f"Cannot access resource {file}.")
    

Vulnerability mechanics

Root cause

"Missing path containment check — `str.startswith()` without a trailing separator allows traversal into a prefix-matching sibling directory."

Attack vector

An unauthenticated attacker sends a crafted GET request to the `/taipy-extension/

Affected code

The vulnerability resides in `ElementLibrary.get_resource()` in `taipy/gui/extension/library.py` [patch_id=2691353]. The method validates path containment using `str(file).startswith(str(base))` without a trailing path separator, allowing a resolved path that has moved into a sibling directory to still pass the check [ref_id=1].

What the fix does

The patch replaces `str(file).startswith(str(base))` with `file.is_relative_to(base)` [patch_id=2691353]. Unlike the string prefix check, `Path.is_relative_to()` performs a true filesystem-path containment test that correctly rejects paths that have escaped the base directory via `..` traversal, even when the resolved path shares a string prefix with the base [ref_id=1].

Preconditions

  • configThe target Taipy application must have a library module whose directory has a prefix-matching sibling directory on disk (e.g. mylib/ and mylib_secrets/).
  • authNo authentication is required; the endpoint is publicly accessible by default.
  • networkThe attacker must be able to send HTTP GET requests to the Taipy server.
  • inputThe attacker supplies path traversal sequences (../ or URL-encoded %2E%2E) in the URL path.

Reproduction

```bash # [1] Baseline — legitimate library resource $ curl -s -o /dev/null -w "HTTP %{http_code}\n" \ "http://127.0.0.1:5005/taipy-extension/mylib/__init__.py" HTTP 200

# [2] LFI via literal "../" in URL $ curl -s --path-as-is \ "http://127.0.0.1:5005/taipy-extension/mylib/../mylib_secrets/creds.txt" AWS_SECRET = AKIA_FAKE_TOKEN_FOR_TAIPY_LFI_POC DATABASE_URL = postgres://admin:hunter2@db.internal/prod

# [3] LFI via URL-encoded ".." $ curl -s --path-as-is \ "http://127.0.0.1:5005/taipy-extension/mylib/%2E%2E/mylib_secrets/creds.txt" AWS_SECRET = AKIA_FAKE_TOKEN_FOR_TAIPY_LFI_POC DATABASE_URL = postgres://admin:hunter2@db.internal/prod ``` [ref_id=1]

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

References

4

News mentions

0

No linked articles in our index yet.