-
-
Notifications
You must be signed in to change notification settings - Fork 30
Update bootstrap.ps1 #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update bootstrap.ps1 #408
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,17 +2,18 @@ | |||||||||
| # Copyright 2019-2025, Namhyeon Go <gnh1201@catswords.re.kr> and the WelsonJS contributors. | ||||||||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||||||||
| # https://github.com/gnh1201/welsonjs | ||||||||||
| # | ||||||||||
| # | ||||||||||
| # Usage: | ||||||||||
| # | ||||||||||
| # Quick start (no arguments): | ||||||||||
| # irm https://catswords.blob.core.windows.net/welsonjs/bootstrap.ps1 | iex | ||||||||||
| # irm https://catswords.blob.core.windows.net/welsonjs/bootstrap.ps1 | iex -dev main | ||||||||||
| # irm https://catswords.blob.core.windows.net/welsonjs/bootstrap.ps1 | iex -dev dev | ||||||||||
| # irm https://catswords.blob.core.windows.net/welsonjs/bootstrap.ps1 | iex main | ||||||||||
| # | ||||||||||
| # Central default branch configuration for this install script. | ||||||||||
| # Update this value if the repository's default branch changes. | ||||||||||
| $defaultBranch = "master" | ||||||||||
| # | ||||||||||
| # With arguments (recommended): | ||||||||||
| # irm https://catswords.blob.core.windows.net/welsonjs/bootstrap.ps1 -OutFile bootstrap.ps1 | ||||||||||
| # .\bootstrap.ps1 -dev main | ||||||||||
| # .\bootstrap.ps1 -file test.js | ||||||||||
|
|
||||||||||
| $defaultBranch = "master" | ||||||||||
| $ErrorActionPreference = "Stop" | ||||||||||
|
|
||||||||||
| function Write-Step($msg) { | ||||||||||
|
|
@@ -29,27 +30,36 @@ function Write-Err($msg) { | |||||||||
|
|
||||||||||
| try { | ||||||||||
| # Step 0: Parse arguments (iex-compatible) | ||||||||||
| # Supports: | ||||||||||
| # iex -dev main | ||||||||||
| # iex main | ||||||||||
| # iex | ||||||||||
| $branch = $defaultBranch | ||||||||||
| $fileArg = $null | ||||||||||
|
|
||||||||||
| for ($i = 0; $i -lt $args.Count; $i++) { | ||||||||||
| $arg = $args[$i] | ||||||||||
|
|
||||||||||
| if ($arg -eq "-dev" -and ($i + 1) -lt $args.Count) { | ||||||||||
| $branch = $args[$i + 1] | ||||||||||
| break | ||||||||||
| $i++ | ||||||||||
| } | ||||||||||
| elseif ($arg -eq "-file" -and ($i + 1) -lt $args.Count) { | ||||||||||
| $fileArg = $args[$i + 1] | ||||||||||
| $i++ | ||||||||||
| } | ||||||||||
| elseif ($arg -notmatch "^-") { | ||||||||||
| $branch = $arg | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Auto-append .js if no extension | ||||||||||
| if ($fileArg -and -not ($fileArg -match "\.")) { | ||||||||||
| $fileArg = "$fileArg.js" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Write-Step "Using branch: $branch" | ||||||||||
| if ($fileArg) { | ||||||||||
| Write-Step "File argument: $fileArg" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Step 1: Create a temporary working directory using a UUID | ||||||||||
| # Step 1: Create temporary workspace | ||||||||||
| Write-Step "Creating temporary workspace..." | ||||||||||
|
|
||||||||||
| $uuid = [guid]::NewGuid().ToString() | ||||||||||
|
|
@@ -62,56 +72,65 @@ try { | |||||||||
| $repo = "gnh1201/welsonjs" | ||||||||||
| $zipPath = Join-Path $tempDir "package.zip" | ||||||||||
|
|
||||||||||
| # Step 2: Build download URL | ||||||||||
| # Step 2: Download from branch | ||||||||||
| $downloadUrl = "https://github.com/$repo/archive/refs/heads/$branch.zip" | ||||||||||
|
|
||||||||||
| Write-Ok "Download URL: $downloadUrl" | ||||||||||
|
|
||||||||||
| # Step 3: Download the ZIP package | ||||||||||
| Write-Step "Downloading package..." | ||||||||||
|
|
||||||||||
| irm $downloadUrl -OutFile $zipPath | ||||||||||
|
|
||||||||||
| Write-Ok "Downloaded: $zipPath" | ||||||||||
|
|
||||||||||
| # Step 4: Extract the ZIP archive | ||||||||||
| # Step 3: Extract | ||||||||||
| Write-Step "Extracting package..." | ||||||||||
|
|
||||||||||
| Expand-Archive -Path $zipPath -DestinationPath $tempDir | ||||||||||
|
|
||||||||||
| Write-Ok "Extraction completed" | ||||||||||
|
|
||||||||||
| # Step 5: Locate bootstrap.bat within extracted files | ||||||||||
| Write-Step "Locating bootstrap.bat..." | ||||||||||
| if ($fileArg) { | ||||||||||
| # Step 4A: Run cscript via cmd (with visible console) | ||||||||||
| Write-Step "Locating app.js..." | ||||||||||
|
|
||||||||||
| $bootstrap = Get-ChildItem -Path $tempDir -Recurse -Filter "bootstrap.bat" | Select-Object -First 1 | ||||||||||
| $app = Get-ChildItem -Path $tempDir -Recurse -Filter "app.js" | Select-Object -First 1 | ||||||||||
|
|
||||||||||
| if (-not $bootstrap) { | ||||||||||
| throw "bootstrap.bat not found" | ||||||||||
| } | ||||||||||
| if (-not $app) { | ||||||||||
| throw "app.js not found" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Write-Ok "Found: $($bootstrap.FullName)" | ||||||||||
| Write-Ok "Found: $($app.FullName)" | ||||||||||
|
|
||||||||||
| # Step 6: Execute bootstrap.bat via cmd.exe for compatibility | ||||||||||
| Write-Step "Executing bootstrap..." | ||||||||||
| Write-Step "Executing via cscript (interactive)..." | ||||||||||
|
|
||||||||||
| $proc = Start-Process -FilePath "cmd.exe" ` | ||||||||||
| -ArgumentList "/c `"$($bootstrap.FullName)`"" ` | ||||||||||
| -Wait -PassThru | ||||||||||
| Start-Process "cmd.exe" ` | ||||||||||
| -ArgumentList "/k cscript `"$($app.FullName)`" `"$fileArg`"" | ||||||||||
|
Comment on lines
+103
to
+104
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -type f -name "bootstrap.ps1" 2>/dev/nullRepository: gnh1201/welsonjs Length of output: 75 🏁 Script executed: cat -n bootstrap.ps1 | head -120 | tail -40Repository: gnh1201/welsonjs Length of output: 1557 🏁 Script executed: cat > /tmp/test_quoting.md << 'EOF'
# PowerShell Start-Process argument passing behavior
When using Start-Process with -ArgumentList, PowerShell passes arguments as a single command line string to the process. For cmd.exe /k:
1. Start-Process receives: "/k cscript `"C:\path with spaces\app.js`" `"arg with spaces`""
2. This becomes the full command line argument to cmd.exe
3. cmd.exe /k then processes this string with its own parsing rules
cmd.exe /k quoting rules (from cmd /?):
- cmd /k interprets the first unquoted string as the command to execute
- Everything after /k becomes the command line to execute
- If the command contains spaces and is NOT quoted, cmd will split at the first space
The issue: If $app.FullName contains spaces, the backtick-escaped quotes may not protect it properly
because cmd.exe receives the entire ArgumentList as a single parameter and applies its own quote parsing.
Proposed fix syntax check:
/k `"cscript `"`"$($app.FullName)`"`" `"`"$fileArg`"`"`"
This would result in nested quotes being passed to cmd.exe which could be problematic.
EOF
cat /tmp/test_quoting.mdRepository: gnh1201/welsonjs Length of output: 1106 🏁 Script executed: # Let me check what actual behavior occurs with Start-Process and cmd.exe argument passing
python3 << 'EOF'
# Analyze the proposed fix syntax
original = '/k cscript `"$($app.FullName)`" `"$fileArg`"'
proposed = '/k `"cscript `"`"$($app.FullName)`"`" `"`"$fileArg`"`"`"'
print("Original quoting:")
print(f" {original}")
print()
print("Proposed quoting:")
print(f" {proposed}")
print()
print("Issue analysis:")
print("- Start-Process passes -ArgumentList as a single string to cmd.exe")
print("- cmd.exe /k applies its own quote-stripping rules")
print("- Backtick escaping in PowerShell handles PowerShell parsing, not cmd.exe parsing")
print()
print("The real issue:")
print("- If $app.FullName contains spaces and cmd.exe strips/misinterprets quotes,")
print(" the command may be split incorrectly")
print("- Example: /k cscript \"C:\\Program Files\\app.js\" \"arg\"")
print(" If cmd strips outer quotes, it becomes: cscript C:\\Program Files\\app.js ...")
print(" And cmd treats 'C:\\Program' as one argument and 'Files\\app.js' as another")
EOFRepository: gnh1201/welsonjs Length of output: 759 🌐 Web query:
💡 Result: To start cmd.exe using PowerShell's Start-Process cmdlet with the /k switch (to execute a command and keep the window open) while properly handling paths containing spaces in ArgumentList, use embedded double-quoting with escaped quotes in PowerShell strings. Official Microsoft documentation recommends using a single string for ArgumentList when dealing with complex quoting: Start-Process -FilePath cmd.exe -ArgumentList "/k dir "%SystemDrive%\Program Files"" This passes cmd.exe /k dir "C:\Program Files" (assuming C: drive), correctly quoting the path with spaces. The "" is PowerShell's escaped double quote. For an array: Start-Process -FilePath cmd.exe -ArgumentList "/k", "dir", ""%SystemDrive%\Program Files"" Both work per docs (results 7,9,10,17 from first search; similar in second). For a custom path with spaces, e.g., $path = "C:\My Folder\script.bat": - Single string (recommended for cmd /k): Start-Process cmd.exe -ArgumentList "/k "$path"" The resulting command line is: cmd.exe /k "C:\My Folder\script.bat" - Array: Start-Process cmd.exe -ArgumentList "/k", ""$path"" Due to a longstanding Start-Process bug (GitHub Citations:
🏁 Script executed: python3 << 'EOF'
# Verify the proposed fix syntax against PowerShell quoting rules
original = r'/k cscript `"$($app.FullName)`" `"$fileArg`"'
proposed = r'/k `"cscript `"`"$($app.FullName)`"`" `"`"$fileArg`"`"`"'
recommended = r'/k `"cscript `"$($app.FullName)`" `"$fileArg`"`"'
print("Current code (as in bootstrap.ps1):")
print(f" -ArgumentList \"{original}\"")
print(" → cmd.exe receives: /k cscript \"...path...\" \"...arg...\"")
print()
print("Proposed fix (from review):")
print(f" -ArgumentList \"{proposed}\"")
print(" Analysis: Multiple nested backtick escapes appear to double-escape")
print()
print("Recommended fix (per cmd /k best practices):")
print(f" -ArgumentList \"{recommended}\"")
print(" → cmd.exe receives: /k \"cscript \"...path...\" \"...arg...\"\"")
print()
print("Key difference:")
print(" - Current: /k cscript ... (if path has spaces, cmd splits incorrectly)")
print(" - Recommended: /k \"cscript ...\" (entire command wrapped, cmd /k respects quotes)")
print()
print("Proposed fix assessment:")
print(" - Syntax is convoluted and may not escape correctly in PowerShell")
print(" - The extra backtick escapes don't follow standard PowerShell quoting patterns")
print(" - A simpler, cleaner fix would be the 'recommended' form above")
EOFRepository: gnh1201/welsonjs Length of output: 975 🏁 Script executed: # Verify the proposed syntax would even be valid PowerShell
python3 << 'EOF'
import re
# Count backtick escapes in proposed fix
proposed = r'/k `"cscript `"`"$($app.FullName)`"`" `"`"$fileArg`"`"`"'
# Each `" should become a literal " in the string
# Let's trace through what PowerShell would produce:
backtick_escaped = re.findall(r'`"', proposed)
print(f"Number of `\" sequences in proposed fix: {len(backtick_escaped)}")
print(f"Positions: {[m.start() for m in re.finditer(r'`\"', proposed)]}")
print()
print("This creates a very complex quoting pattern that may be error-prone")
print("and doesn't match standard PowerShell/cmd quoting conventions")
EOFRepository: gnh1201/welsonjs Length of output: 306 Correct the cmd.exe /k argument quoting to handle paths with spaces. The concern about cmd.exe /k quote-stripping is valid when Proposed fix- Start-Process "cmd.exe" `
- -ArgumentList "/k cscript `"$($app.FullName)`" `"$fileArg`""
+ Start-Process "cmd.exe" `
+ -ArgumentList "/k `"cscript `"$($app.FullName)`" `"$fileArg`"`""Alternatively, 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
|
Comment on lines
+103
to
105
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Unvalidated $filearg in cmd.exe $fileArg (user-controlled via -file) is interpolated into a cmd.exe command line without validation/escaping, so quotes/metacharacters can break argument parsing or enable command injection. This violates the requirement to validate inputs/constraints before operating on them. Agent Prompt
Comment on lines
+103
to
105
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Wrong cscript bitness In -file mode, bootstrap.ps1 launches cscript via cmd.exe without forcing the 32-bit
SysWOW64\cscript.exe that bootstrap.bat uses, which can break scripts that depend on the 32-bit
WelsonJS.Toolkit COM registration. This can cause runtime failures (e.g.,
CreateObject('WelsonJS.Toolkit')) in the launched session even though bootstrap.ps1 reports it
started successfully.
Agent Prompt
|
||||||||||
| if ($proc.ExitCode -ne 0) { | ||||||||||
| throw "bootstrap failed with exit code $($proc.ExitCode)" | ||||||||||
| Write-Ok "cscript launched (interactive console)" | ||||||||||
| } | ||||||||||
| else { | ||||||||||
| # Step 4B: Default bootstrap (non-blocking) | ||||||||||
| Write-Step "Locating bootstrap.bat..." | ||||||||||
|
|
||||||||||
| $bootstrap = Get-ChildItem -Path $tempDir -Recurse -Filter "bootstrap.bat" | Select-Object -First 1 | ||||||||||
|
|
||||||||||
| if (-not $bootstrap) { | ||||||||||
| throw "bootstrap.bat not found" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| Write-Ok "Bootstrap executed successfully" | ||||||||||
| Write-Ok "Found: $($bootstrap.FullName)" | ||||||||||
|
|
||||||||||
| Write-Step "Executing bootstrap (non-blocking)..." | ||||||||||
|
|
||||||||||
| Start-Process "cmd.exe" ` | ||||||||||
| -ArgumentList "/c `"$($bootstrap.FullName)`"" | ||||||||||
|
|
||||||||||
| Write-Ok "Bootstrap launched" | ||||||||||
|
Comment on lines
+120
to
+125
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Fire-and-forget start-process call The script launches bootstrap.bat with Start-Process without -Wait/-PassThru, so failures and non-zero exit codes are not observed or reported. This matches the checklist’s prohibition on unobserved fire-and-forget operations where faults can be lost. Agent Prompt
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| # Step 7: Final message | ||||||||||
| Write-Host "" | ||||||||||
| Write-Host "WelsonJS installation completed!" -ForegroundColor Green | ||||||||||
| Write-Host "WelsonJS execution started!" -ForegroundColor Green | ||||||||||
| Write-Host "" | ||||||||||
|
|
||||||||||
| } | ||||||||||
| catch { | ||||||||||
| Write-Err $_ | ||||||||||
| exit 1 | ||||||||||
| } | ||||||||||
| } | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extension check matches any dot in the path, not just an extension.
$fileArg -match "\."returns true for inputs likemy.app,sub.dir/test, or any path containing a dot, so.jswill not be appended even when there is no real extension. Use a proper extension check instead.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents