You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ossie.apache.org by ce...@apache.org on 2026/10/21 02:56:16 UTC

(ossie) branch main updated: fix(cube): reject drive, NUL and non-string components in stashed paths (#533)

This is an automated email from the ASF dual-hosted git repository.

christianeu-db pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ossie.git


The following commit(s) were added to refs/heads/main by this push:
     new 2b0209cf fix(cube): reject drive, NUL and non-string components in stashed paths (#533)
2b0209cf is described below

commit 2b0209cfe3910f4b7138d364b1f56afc758208ef
Author: JB Onofré <jb...@apache.org>
AuthorDate: Wed Oct 21 03:56:10 2026 +0100

    fix(cube): reject drive, NUL and non-string components in stashed paths (#533)
    
    * fix(cube): reject drive, NUL and non-string components in stashed paths
    
    * test(cube): accept the NUL byte message in the stashed path test
---
 converters/cube/src/ossie_cube/_common.py | 12 +++++++++++-
 converters/cube/tests/test_osi_to_cube.py | 15 ++++++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/converters/cube/src/ossie_cube/_common.py b/converters/cube/src/ossie_cube/_common.py
index ac98cb52..ca14e0bf 100644
--- a/converters/cube/src/ossie_cube/_common.py
+++ b/converters/cube/src/ossie_cube/_common.py
@@ -504,7 +504,12 @@ def safe_relative_path(path, what):
     directory the caller named. Refuses anything that is not a plain relative path
     inside the output root.
     """
-    raw = str(path)
+    if not isinstance(path, str):
+        raise ConversionError(
+            f"{what}: stashed file path must be a string, got {type(path).__name__}")
+    raw = path
+    if "\x00" in raw:
+        raise ConversionError(f"{what}: stashed file path contains a NUL byte")
     if not raw.strip():
         raise ConversionError(f"{what}: stashed file path is empty")
     if raw.startswith(("/", "\\")) or re.match(r"^[A-Za-z]:", raw):
@@ -512,6 +517,11 @@ def safe_relative_path(path, what):
             f"{what}: stashed file path '{raw}' is absolute; expected a path "
             f"relative to the output directory")
     parts = [p for p in raw.replace("\\", "/").split("/") if p not in ("", ".")]
+    # A drive on any component makes ntpath.join reset to it, so check each one.
+    if any(re.match(r"^[A-Za-z]:", p) for p in parts):
+        raise ConversionError(
+            f"{what}: stashed file path '{raw}' is absolute; expected a path "
+            f"relative to the output directory")
     if any(p == ".." for p in parts):
         raise ConversionError(
             f"{what}: stashed file path '{raw}' escapes the output directory")
diff --git a/converters/cube/tests/test_osi_to_cube.py b/converters/cube/tests/test_osi_to_cube.py
index e65558fd..406d6f24 100644
--- a/converters/cube/tests/test_osi_to_cube.py
+++ b/converters/cube/tests/test_osi_to_cube.py
@@ -926,6 +926,8 @@ def test_synonyms_reach_cube_as_prose_and_are_parked_structurally():
     ("cube_files", "/etc/outside.yml"),
     ("view_files", "../escaped.yml"),
     ("extra_files", "../../notes.txt"),
+    ("cube_files", "cubes/C:evil.yml"),
+    ("cube_files", "a\x00b.yml"),
 ])
 def test_a_stashed_path_may_not_escape_the_output_directory(key, path):
     """The stash is part of the input document, so a path in it is untrusted. Export
@@ -946,7 +948,7 @@ def test_a_stashed_path_may_not_escape_the_output_directory(key, path):
         "custom_extensions:\n"
         "- vendor_name: CUBE\n"
         f"  data: '{json.dumps(stash)}'\n")
-    with pytest.raises(ConversionError, match="absolute|escapes the output"):
+    with pytest.raises(ConversionError, match="absolute|escapes the output|NUL byte"):
         convert_ossie_to_cube(ossie)
 
 
@@ -1398,3 +1400,14 @@ def test_ansi_sql_is_preferred_over_ossie_sql():
         {"dialect": "ANSI_SQL", "expression": "b"}]}
     assert pick_expression(expression) == ("b", "ANSI_SQL")
     assert pick_expression(expression, "OSSIE_SQL_2026") == ("a", "OSSIE_SQL_2026")
+
+
+def test_a_non_string_stashed_path_is_rejected():
+    import json
+    stash = {"_v": 1, "views": {}, "cube_files": {"orders": ["a", "b"]}}
+    ossie = _ossie(_ORDERS) + (
+        "custom_extensions:\n"
+        "- vendor_name: CUBE\n"
+        f"  data: '{json.dumps(stash)}'\n")
+    with pytest.raises(ConversionError, match="must be a string"):
+        convert_ossie_to_cube(ossie)