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

imbajin pushed a commit to branch feat/oink-core-platform
in repository https://gitbox.apache.org/repos/asf/hugegraph-doc.git

commit 1e7258f99f797153714c280d2c49c1d678dff01e
Author: dark <[email protected]>
AuthorDate: Fri Sep 4 22:25:58 2026 +0800

    fix(versioning): reject symlinked runner temp
    
    - fail closed before resolving RUNNER_TEMP
    - preserve output contents behind temp aliases
    - cover normal and symlinked cleanup roots
---
 scripts/test_versioning.py | 28 ++++++++++++++++++++++++++++
 scripts/versioning.py      |  8 +++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/scripts/test_versioning.py b/scripts/test_versioning.py
index 61e5a187d..067e18100 100644
--- a/scripts/test_versioning.py
+++ b/scripts/test_versioning.py
@@ -1262,6 +1262,34 @@ class VersionUrlTest(unittest.TestCase):
             self.assertEqual(sentinel.read_text(encoding="utf-8"), "keep")
             self.assertTrue(output.is_dir())
 
+    def test_output_cleanup_rejects_symlinked_runner_temp_before_resolve(
+        self,
+    ) -> None:
+        with tempfile.TemporaryDirectory() as temp_name:
+            temp = Path(temp_name)
+            target = temp / "target"
+            output = target / "output"
+            output.mkdir(parents=True)
+            sentinel = output / "sentinel"
+            sentinel.write_text("keep", encoding="utf-8")
+            runner_temp = temp / "runner-temp"
+            runner_temp.symlink_to(target, target_is_directory=True)
+
+            with (
+                mock.patch.dict(
+                    versioning.os.environ,
+                    {"RUNNER_TEMP": str(runner_temp)},
+                ),
+                self.assertRaisesRegex(SystemExit, "symbolic link"),
+            ):
+                versioning.prepare_output_directory(
+                    runner_temp / "output",
+                    "fixture",
+                )
+
+            self.assertEqual(sentinel.read_text(encoding="utf-8"), "keep")
+            self.assertTrue(output.is_dir())
+
     def test_output_cleanup_rejects_registered_sibling_worktree(self) -> None:
         with tempfile.TemporaryDirectory() as temp_name:
             sibling = Path(temp_name) / "registered-sibling"
diff --git a/scripts/versioning.py b/scripts/versioning.py
index b20c7a79c..dade4b69b 100644
--- a/scripts/versioning.py
+++ b/scripts/versioning.py
@@ -349,7 +349,13 @@ def prepare_output_directory(path: pathlib.Path, label: 
str) -> pathlib.Path:
     }
     runner_temp = os.environ.get("RUNNER_TEMP")
     if runner_temp:
-        controlled_roots.add(pathlib.Path(runner_temp))
+        runner_temp_root = pathlib.Path(runner_temp).expanduser()
+        if runner_temp_root.is_symlink():
+            fail(
+                "RUNNER_TEMP must not be a symbolic link: "
+                f"{runner_temp_root}"
+            )
+        controlled_roots.add(runner_temp_root)
     raw_absolute = require_no_symlinked_output_components(
         raw, label, controlled_roots
     )

Reply via email to