* Studio: drop the VBS launcher to clear the Kaspersky false positive
The Windows shortcut launched Unsloth Studio through wscript.exe ->
launch-studio.vbs, and that VBS used CreateObject("WScript.Shell").Run to
start a hidden -ExecutionPolicy Bypass PowerShell. That wscript + .vbs +
bypass-powershell shape is the canonical trigger for generic VBS-dropper
heuristics (Kaspersky HEUR:Trojan.VBS.Agent.gen). The launcher is benign;
only its shape is the problem.
- install.ps1: stop generating launch-studio.vbs and point the Desktop /
Start Menu .lnk straight at powershell.exe -WindowStyle Hidden running
launch-studio.ps1. The shortcut is saved WindowStyle 7 (minimized) so the
brief console flash is muted. launch-studio.ps1 (health poll, port,
mutex, browser) is byte-for-byte unchanged.
- install.ps1: delete a pre-existing launch-studio.vbs on upgrade, so the
flagged file does not linger on machines that already installed it.
- install.ps1 / install.sh: run the heavier ie4uinit -ClearIconCache plus
StartMenuExperienceHost tile-cache rebuild only on a first install or a
real icon change, instead of on every no-op reinstall. That repeated
clear-cache plus kill cluster is itself a dropper-like behavioral pattern.
- tests: forbid VBS generation and require the legacy-VBS cleanup.
Linux, macOS and WSL install paths are unchanged. WSL already targets
wsl.exe from its .lnk and never used a VBS; its only change is the same
icon-cache gating.
* Studio: add launcher-chain smoke coverage to the Windows UI CI
The shortcut launch path was previously untested: studio-windows-ui-smoke
installed then booted `unsloth studio` directly, so a broken .lnk could ship
silently. After install the job now seeds a legacy launch-studio.vbs, asserts
the upgrade removed it, asserts the .lnk targets hidden powershell.exe (never
wscript.exe), and launches via the shortcut's stored command, waiting for
/api/health to report healthy.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
"""Guard install.ps1's Studio launcher against re-introducing the AV-heuristic
|
|
shape: a WScript .vbs that spawns a hidden, ExecutionPolicy-Bypass PowerShell
|
|
(Kaspersky HEUR:Trojan.VBS.Agent.gen). The shortcut must stay windowless via
|
|
powershell.exe -WindowStyle Hidden over launch-studio.ps1 -- never a .vbs /
|
|
WScript.Shell.Run wrapper. Any pre-existing .vbs from an older install must be
|
|
deleted, not merely left behind."""
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[3]
|
|
INSTALL_PS1 = REPO_ROOT / "install.ps1"
|
|
|
|
|
|
def _text() -> str:
|
|
return INSTALL_PS1.read_text(encoding = "utf-8")
|
|
|
|
|
|
def test_install_ps1_present():
|
|
assert INSTALL_PS1.is_file(), f"missing {INSTALL_PS1}"
|
|
|
|
|
|
def test_no_vbs_launcher_generated():
|
|
text = _text()
|
|
# No here-string that builds a .vbs body, and no .vbs file written. (A
|
|
# Remove-Item cleanup of the legacy .vbs is allowed and checked separately.)
|
|
assert "$vbsContent" not in text, (
|
|
"install.ps1 must not generate a launch-studio.vbs: a WScript.Shell .vbs "
|
|
"spawning a hidden ExecutionPolicy-Bypass PowerShell is the exact shape "
|
|
"VBS-dropper heuristics flag (Kaspersky HEUR:Trojan.VBS.Agent.gen)."
|
|
)
|
|
assert 'CreateObject("WScript.Shell")' not in text
|
|
assert "shell.Run" not in text
|
|
assert not re.search(r"Set-Content\s+-LiteralPath\s+\$launcherVbs", text)
|
|
assert "//B //Nologo" not in text
|
|
|
|
|
|
def test_legacy_vbs_removed_on_upgrade():
|
|
# The whole point: an upgrade must DELETE a pre-existing launch-studio.vbs,
|
|
# not just stop generating it, or AV keeps flagging the stale file.
|
|
text = _text()
|
|
assert re.search(
|
|
r"Remove-Item\s+-LiteralPath\s+\$legacyLauncherVbs", text
|
|
), "upgrades must remove a pre-existing launch-studio.vbs so AV stops flagging it"
|
|
|
|
|
|
def test_shortcut_target_is_not_wscript():
|
|
# The .lnk must not be launched through wscript.exe (the VBS script host).
|
|
text = _text()
|
|
assert "wscript.exe" not in text.lower()
|
|
|
|
|
|
def test_launcher_is_windowless_powershell():
|
|
# The shortcut runs powershell.exe with a hidden window over launch-studio.ps1.
|
|
text = _text()
|
|
assert re.search(
|
|
r"-WindowStyle\s+Hidden", text
|
|
), "the launcher must run powershell.exe with -WindowStyle Hidden over launch-studio.ps1."
|
|
assert "launch-studio.ps1" in text
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(pytest.main([__file__, "-v"]))
|