Fix deployment bugs, rework hardening, add opt-in BitLocker and WinUtil steps - #48
Open
Stensel8 wants to merge 4 commits into
Open
Fix deployment bugs, rework hardening, add opt-in BitLocker and WinUtil steps#48Stensel8 wants to merge 4 commits into
Stensel8 wants to merge 4 commits into
Conversation
…il steps Audit of the deployment scripts turned up several bugs that break a zero-touch run, plus a hardening baseline that both did too much in one place and too little in another. Bugs fixed: - Docs/autounattend.xml never launched WinDeploy. The first-logon script was generated as unattend-02.cmd but contained PowerShell, which cmd.exe cannot run. Made it a .ps1 and corrected the generator URL. - Harden-Windows.ps1 set SMB2=0, which disables SMB2 *and* SMB3 and breaks all file and printer sharing. Removed; replaced with SMB signing and guest-logon hardening. - Test-IntuneEnrollment and Deploy.ps1 both crashed under StrictMode ($null.Count, and $LASTEXITCODE before it is ever set). $LASTEXITCODE also leaked between steps, marking later steps as failed. - Screen lock was written to HKCU, which during deployment is the deployment account rather than the end user, and SCRNSAVE.EXE was empty so the secure lock never triggered. Now machine-wide policy. - winget installs were missing --silent, and Office used Display Level="Full", so both could show UI mid-deployment. - Windows updates without a KB number (drivers, definitions) were silently skipped by the per-KB install loop. - Seven winget font error codes were typed -1979335xxx, not -1978335xxx. - HP detection matched "*hp*", which also matches "Sharp"; HPCMSL was installed without bootstrapping NuGet/PSGallery so it stalled. - Remove-Bloat logged to %TEMP% instead of C:\WinDeploy\Logs, used a PowerShell 6+ escape in a 5.1 script, and never implemented the "prevents reinstall" its header promised. - Exit prompts now time out instead of blocking unattended runs. BitLocker previously created only a TPM protector while telling the operator to "export your BitLocker recovery key" that never existed, leaving the drive unrecoverable after a TPM clear or mainboard swap. It now asks Y/N, creates a recovery password, saves it to the operator's Documents folder and prints it on screen with a warning to store it. Added Apply-Tweaks.ps1, an opt-in step that applies a ChrisTitusTech WinUtil preset after a Y/N confirmation, and extended the hardening baseline with LSA protection, WDigest, SMB signing, LLMNR, HVCI and Defender ASR rules. Both prompts default to No after 90s, and -NonInteractive skips them entirely for the autounattend path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pt5Q3XvjMT6HMdubvkyLMW
…s properly
Smoke-testing the new confirmation prompts turned up two problems in the
code added in the previous commit.
Read-YesNoWithTimeout used Write-Output for its "no console" message.
Write-Output goes to the same stream as the return value, so the caller
got @("...message...", $false) instead of $false. A 2-element array is
truthy, so `if (-not $enableBitLocker)` took the wrong branch and
answering No would have ENABLED BitLocker. Switched to Write-Host, which
does not touch the output stream, and added a test asserting the return
value is a clean [bool].
The non-interactive short-circuit also never fired. [Environment]::
UserInteractive is $true for any process in a user session, including one
with redirected stdin, so the helper fell through to the polling loop and
sat there for the full 90-second timeout instead of returning the default
immediately. Now also checks [Console]::IsInputRedirected, and Deploy.ps1's
Wait-ForExit got the same guard.
While there: the countdown repainted once a second, which fills the
Start.ps1 transcript with 90 redraw lines per prompt. It now repaints
every 5 seconds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pt5Q3XvjMT6HMdubvkyLMW
DevSkim reported three errors on this PR, all "A potentially weak cipher mode of operation was used". Fetched the check-run annotations rather than guessing: all three are the literal prose string "XTS-AES-256" in a console message, a summary label and a docs-link key. DS187371 word-matches XTS from a list of cipher modes. The hyphens in "XTS-AES-256" form word boundaries, which is why the prose matches while the actual code (-EncryptionMethod XtsAes256) does not. The finding is wrong on the merits: XTS is the mode Microsoft recommends for BitLocker, and it is what this script configures. Rewording cannot fix it either, since any text naming the mode matches, and dropping the name would hide information the operator wants. Suppressed inline with a justification, which is DevSkim's own mechanism for this. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pt5Q3XvjMT6HMdubvkyLMW
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pt5Q3XvjMT6HMdubvkyLMW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Audit of the deployment scripts. Several bugs break a zero-touch run; the hardening baseline did too much in one place and too little in another. Adds BitLocker behind a Y/N prompt and an optional WinUtil tweak step.
The three that matter most:
Docs/autounattend.xmlnever launched WinDeploy. The first-logon script was generated asunattend-02.cmdbut contained PowerShell, whichcmd.execannot run, so Option 1 in the README was broken end to end.SMB2 = 0, which disables SMB2 and SMB3 and breaks file and printer sharing.Also fixed: two
Set-StrictModecrashes ($null.Count,$LASTEXITCODEbefore it is set, which also leaked between steps), screen lock written to the deployment account'sHKCUwith an emptySCRNSAVE.EXE,winget installmissing--silent, Office installing interactively, updates without a KB number skipped, seven mistyped winget error codes, HP detection matching "Sharp",HPCMSLinstalled without bootstrapping NuGet/PSGallery, andRemove-Bloatlogging to the wrong directory. Full list in the CHANGELOG.New:
Apply-Tweaks.ps1runs a WinUtil preset after a Y/N prompt, in its own process. Hardening extended with LSA protection, WDigest, SMB signing, LLMNR, HVCI and 9 Defender ASR rules. Both prompts default to No after 90s;-NonInteractiveskips them and is passed through byautounattend.xml.Type of change
Testing
Verified with PowerShell 7.5.4 and PSScriptAnalyzer 1.24: all 18 scripts parse clean, 0 findings, both
validate.ymljobs reproduced locally,autounattend.xmlwell-formed with CRLF preserved.Notes
Needs a real 25H2 machine before merge. Nothing was executed against Windows — BitLocker, TPM, Sysprep, winget, Defender ASR and the registry writes are unexercised.
Worth checking while testing:
Start-JobthatRemove-Job -Forcecould kill.Three inline
# DevSkim: ignore DS187371suppressions inHarden-Windows.ps1: DevSkim word-matchesXTSfrom its weak-cipher-mode list, so the prose "XTS-AES-256" was reported as three errors. XTS is the mode Microsoft recommends for BitLocker, and any text naming it matches, so it is suppressed with a justification.Version bumped to
v0.8.0.Generated by Claude Code