From 155423532c92fbb1f74bfb0256e8a0e7260cee9b Mon Sep 17 00:00:00 2001 From: Lyxot Date: Tue, 7 Jul 2026 21:10:09 +0800 Subject: [PATCH] fix(studio): validate launcher install id --- install.ps1 | 2 +- install.sh | 12 +++++++++++- tests/test_studio_install_workspace_guard.py | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/install.ps1 b/install.ps1 index c6d4045896..41bbca0518 100644 --- a/install.ps1 +++ b/install.ps1 @@ -598,7 +598,7 @@ function Install-UnslothStudio { ((Get-Item -LiteralPath $_studioIdFile).Length -gt 0)) { $_studioRootId = ([System.IO.File]::ReadAllText($_studioIdFile)).Trim() } - if (-not $_studioRootId) { + if ($_studioRootId -notmatch '^[0-9a-f]{64}$') { $_idBytes = New-Object byte[] 32 [Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($_idBytes) $_studioRootId = -join ($_idBytes | ForEach-Object { $_.ToString('x2') }) diff --git a/install.sh b/install.sh index cef91610ca..17f446ef85 100755 --- a/install.sh +++ b/install.sh @@ -598,7 +598,16 @@ create_studio_shortcuts() { _css_id_dir="$STUDIO_HOME/share" mkdir -p "$_css_id_dir" _css_id_file="$_css_id_dir/studio_install_id" - if [ ! -s "$_css_id_file" ]; then + _css_existing_id="" + [ -f "$_css_id_file" ] && _css_existing_id=$(cat "$_css_id_file" 2>/dev/null || true) + _css_existing_id_valid=false + if [ "${#_css_existing_id}" -eq 64 ]; then + case "$_css_existing_id" in + *[!0-9a-f]*) ;; + *) _css_existing_id_valid=true ;; + esac + fi + if [ "$_css_existing_id_valid" != "true" ]; then if [ -r /dev/urandom ]; then _css_new_id=$(od -An -N32 -tx1 /dev/urandom 2>/dev/null | tr -d ' \n') fi @@ -616,6 +625,7 @@ create_studio_shortcuts() { chmod 600 "$_css_id_file" 2>/dev/null || true unset _css_new_id _css_id_tmp fi + unset _css_existing_id _css_existing_id_valid _css_studio_root_id=$(cat "$_css_id_file" 2>/dev/null) if [ -z "$_css_studio_root_id" ]; then echo "[WARN] Cannot create launcher: failed to read $_css_id_file" >&2 diff --git a/tests/test_studio_install_workspace_guard.py b/tests/test_studio_install_workspace_guard.py index f25466d594..64164e5756 100644 --- a/tests/test_studio_install_workspace_guard.py +++ b/tests/test_studio_install_workspace_guard.py @@ -514,6 +514,9 @@ def test_install_ps1_bakes_studio_root_id_into_launcher(): assert ( "$_ExpectedStudioRootId" in src ), "install.ps1 must bake $_ExpectedStudioRootId into the launcher" + assert ( + "$_studioRootId -notmatch '^[0-9a-f]{64}$'" in src + ), "install.ps1 must regenerate invalid existing studio_install_id values before baking" def test_install_ps1_launcher_repairs_missing_studio_install_id(): @@ -578,6 +581,9 @@ def test_install_sh_bakes_studio_root_id_into_launcher(): assert ( "s|@@STUDIO_ROOT_ID@@|$_css_studio_root_id|g" in src ), "install.sh must sed-substitute @@STUDIO_ROOT_ID@@ unconditionally (not just env-mode)" + assert ( + "_css_existing_id_valid" in src + ), "install.sh must validate existing studio_install_id values before baking" def test_install_sh_launcher_repairs_missing_studio_install_id(tmp_path):