cschneegans / unattend-generator

.NET Core library to create highly customized autounattend.xml files
https://schneegans.de/windows/unattend-generator/
MIT License
659 stars 60 forks source link

improper escaping of ampersand char & in many options. #75

Closed Chaos02 closed 1 month ago

Chaos02 commented 1 month ago

Hey, really love your project but the page generates invalid XML files by improperly escaping the Ampersand & character in many places.

Here are some examples of what I found:

<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>cmd.exe /c "netsh.exe wlan add profile filename="%TEMP%\wifi.xml" user=all >>"%TEMP%\wifi.log" 2>&1"</Path>
</RunSynchronousCommand>

needs to be

<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>cmd.exe /c "netsh.exe wlan add profile filename="%TEMP%\wifi.xml" user=all >>"%TEMP%\wifi.log" 2>&amp;1"</Path>
</RunSynchronousCommand>

and

<Order>2</Order>
<CommandLine>cmd.exe /c "powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\unattend-01.ps1' -Raw | Invoke-Expression;" >>"C:\Windows\Setup\Scripts\unattend-01.log" 2>&1"</CommandLine>
</SynchronousCommand>
</FirstLogonCommands>

needs to be

<Order>2</Order>
<CommandLine>cmd.exe /c "powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\unattend-01.ps1' -Raw | Invoke-Expression;" >>"C:\Windows\Setup\Scripts\unattend-01.log" 2>&amp;1"</CommandLine>
</SynchronousCommand>
</FirstLogonCommands>

aswell as anything written into

<Extensions xmlns="https://schneegans.de/windows/unattend-generator/">
<ExtractScript> param( [xml] $Document ); $scriptsDir = 'C:\Windows\Setup\Scripts\'; foreach( $file in $Document.unattend.Extensions.File ) { $path = [System.Environment]::ExpandEnvironmentVariables( $file.GetAttribute( 'path' ) ); if( $path.StartsWith( $scriptsDir ) ) { mkdir -Path $scriptsDir -ErrorAction 'SilentlyContinue'; } $encoding = switch( [System.IO.Path]::GetExtension( $path ) ) { { $_ -in '.ps1', '.xml' } { [System.Text.Encoding]::UTF8; } { $_ -in '.reg', '.vbs', '.js' } { [System.Text.UnicodeEncoding]::new( $false, $true ); } default { [System.Text.Encoding]::Default; } }; [System.IO.File]::WriteAllBytes( $path, ( $encoding.GetPreamble() + $encoding.GetBytes( $file.InnerText.Trim() ) ) ); } </ExtractScript>
<File path="C:\Windows\Temp\remove-packages.ps1"> ......
<File path="C:\Windows\Temp\remove-caps.ps1"> .....

Is also escaped improperly. as a result the unattend.xml does not work.

hoang-himself commented 1 month ago

Not escaping seems to work just fine, if you can ignore the linter.

cschneegans commented 1 month ago

All XML documents generated by my service are well-formed and valid, of course. In particular, the ampersand character in the line

<Path>cmd.exe /c "netsh.exe wlan add profile filename="%TEMP%\wifi.xml" user=all &gt;&gt;"%TEMP%\wifi.log" 2&gt;&amp;1"</Path>

is properly escaped. I assume that you view the autounattend.xml file in a browser such as Chrome, which renders the text value of XML elements (rather than their source code):

image

This is not the actual XML document, however.

Chaos02 commented 1 month ago

Actually, I pulled the examples out of vscode as I was adding the disk checking module from Windows. I DID make sure that that section is right so something else seems to be off. There we're unescaped ampersands everywhere in the file. It might have been copy pasted from the browser, don't remember but thanks for looking into it so quickly. In that case I would recommend displaying a hint next to the "view XML" button or rendering the XML on the website itself if possible (so not a "download link" to the raw file)