Found reviewing PR #232. Verified against install.cmd as merged.
What happens
When install.ps1 is not next to it, install.cmd downloads one and runs it:
set "PS1_URL=https://raw.githubusercontent.com/SOFTNETWORK-APP/SoftClient4ES/refs/heads/main/install.ps1"
...
set "PS1=%TEMP%\softclient4es-install.ps1"
curl.exe -fsSL -o "%PS1%" "%PS1_URL%"
...
powershell -NoProfile -ExecutionPolicy Bypass -File "%PS1%" %*
The fallback itself is intended and documented — "When install.ps1 is not sitting next to it, it downloads one, so install.cmd on its own is a complete install". Three properties of how it does it are the problem:
- The URL is
refs/heads/main, unpinned. The file's own comment two lines above says: "A local install.ps1 always wins: a downloaded pair must stay self-consistent, and a released bundle must never be silently mixed with main." An install.cmd shipped in a released bundle, separated from its install.ps1 for any reason, fetches main and produces exactly the mix the comment forbids — silently, since a user who ran the released .cmd has no reason to think they are running main.
- No integrity check. The script is fetched over TLS and executed with
-ExecutionPolicy Bypass, with nothing verifying it is the file the release intended — no tag, no checksum, no signature.
%TEMP%\softclient4es-install.ps1 is never cleaned up, and it is a fixed, predictable path in a world-writable directory that is then executed with Bypass.
Suggested fix
- Pin the URL to a tag rather than
main — the released .cmd should fetch the install.ps1 of the release it belongs to. The version is already a concept in this script family, so it can be substituted at release time or defaulted to the newest tag.
- Verify what was downloaded before running it (published SHA-256 alongside the release is the cheapest option that actually closes it).
- Write to a unique temp path and delete it after the run.
main remains a reasonable default for someone who deliberately fetches install.cmd from main — the point is that the released artefact should not silently do it.
Found reviewing PR #232. Verified against
install.cmdas merged.What happens
When
install.ps1is not next to it,install.cmddownloads one and runs it:The fallback itself is intended and documented — "When install.ps1 is not sitting next to it, it downloads one, so install.cmd on its own is a complete install". Three properties of how it does it are the problem:
refs/heads/main, unpinned. The file's own comment two lines above says: "A local install.ps1 always wins: a downloaded pair must stay self-consistent, and a released bundle must never be silently mixed with main." Aninstall.cmdshipped in a released bundle, separated from itsinstall.ps1for any reason, fetchesmainand produces exactly the mix the comment forbids — silently, since a user who ran the released.cmdhas no reason to think they are runningmain.-ExecutionPolicy Bypass, with nothing verifying it is the file the release intended — no tag, no checksum, no signature.%TEMP%\softclient4es-install.ps1is never cleaned up, and it is a fixed, predictable path in a world-writable directory that is then executed with Bypass.Suggested fix
main— the released.cmdshould fetch theinstall.ps1of the release it belongs to. The version is already a concept in this script family, so it can be substituted at release time or defaulted to the newest tag.mainremains a reasonable default for someone who deliberately fetchesinstall.cmdfrommain— the point is that the released artefact should not silently do it.