Bug: windows-restart provisioner runs hardcoded DefaultRestartCheckCommand even when restart_check_command is overridden, breaking Windows Constrained Language Mode.
- Dominant language
- Go
- Stars
- 15.8k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
#### Community Note
* Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request
* Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
* If you are interested in working on this issue or have submitted a pull request, please leave a comment
#### Overview of the Issue
When using the `windows-restart` provisioner on a Windows VM (e.g., Windows 11) that has PowerShell Constrained Language Mode enabled, providing a custom `restart_check_command` does not bypass the default PowerShell checks as one would expect from the documentation.
Even if the custom check succeeds, the provisioner subsequently runs a hardcoded check using `[System.Net.Dns]::GetHostName()`, which fails due to Constrained Language restrictions, causing the entire build to fail.
**Expected Behavior:**
If a user explicitly provides a custom `restart_check_command`, Packer should rely entirely on that command to verify the restart and communicator state. It should *not* blindly execute `DefaultRestartCheckCommand` afterwards.
**Actual Behavior:**
The custom `restart_check_command` is executed and succeeds. Immediately after logging `Connected to machine`, the `waitForCommunicator` function executes `DefaultRestartCheckCommand` as a "non-user-configurable check that powershell modules have loaded" (as stated in the source code comments). Because `DefaultRestartCheckCommand` relies on `[System.Net.Dns]::GetHostName()`, which is blocked in Constrained Language Mode, the command exits with code 1 and hangs/fails the build.
**Relevant Code:**
In `packer-plugin-sdk/restart/provisioner.go` within the `waitForCommunicator` function (around line 220-231):
````go
if runCustomRestartCheck {
// ... runs user command and succeeds
log.Printf("Connected to machine")
runCustomRestartCheck = false
}
// BUG/ISSUE: This executes regardless of the custom command override:
cmdModuleLoad := &packersdk.RemoteCmd{Command: DefaultRestartCheckCommand}
````
#### Reproduction Steps
1. Provision a Windows VM and enable PowerShell Constrained Language Mode.
2. Add a `windows-restart` provisioner to the Packer template.
3. Configure `restart_check_command = "powershell -command \"& {Write-Output 'restarted.'}\""` to attempt bypassing the default check.
4. Run the build. The build fails on the restart check due to the hardcoded `DefaultRestartCheckCommand` overriding the custom check.
### Packer version
1.15.3
### Simplified Packer Template
````hcl
provisioner "windows-restart" {
restart_timeout = "30m"
restart_check_command = "powershell -command \"& {Write-Output 'restarted.'}\""
}
````
### Operating system and Environment details
* **Guest OS:** Windows 11
* **Guest Configuration:** PowerShell Constrained Language Mode enabled via a task
* **Build Environment:** GitHub Actions CI/CD
* **Builder:** `vsphere-iso` (using `packer-plugin-vsphere`)
### Log Fragments and crash.log files
````text
[DEBUG] starting remote command: powershell -command "& {Write-Output 'restarted.'}"
ui: vsphere-iso.vdi-image: restarted.
packer.exe plugin: Connected to machine
[DEBUG] starting remote command: powershell.exe -EncodedCommand JABQAHIAbwBnAHIAZQBzAHMAUAByAGUAZgBlAHIAZQBuAGMAZQAgAD0AIAAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwA7AGUAYwBoAG8AIAAoACIAewAwAH0AIAByAGUAcwB0AGEAcgB0AGUAZAAuACIAIAAtAGYAIABbAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBEAG4AcwBdADoAOgBHAGUAdABIAG8AcwB0AE4AYQBtAGUAKAApACkA
[ERROR] Remote command exited with '1': powershell.exe -EncodedCommand JABQAHIAbwBnAHIA...
````
*(Note: The Base64 encoded string decodes directly to: `$ProgressPreference = 'SilentlyContinue';echo ("{0} restarted." -f [System.Net.Dns]::GetHostName())`, proving the hardcoded check is executed despite the override).*
Contributor guide
Assessment
This issue has not been assessed yet.