Pas trop chaud en ce moment ? Si vous êtes en vacances, ne lisez pas cet article ! Mais si vous êtes au bureau … un fichier douteux a peut-être atterri sur votre poste, ou un exe reçu par mail, ou encore un script « lance ça pour réparer ton VPN ». Bref, vous devez l’ouvrir pour vérifier sans risquer votre machine ni le réseau de l’entreprise.

Cet article est fait pour vous. On va monter, étape par étape, une sandbox Windows jetable et durcie pour analyser un fichier hors-ligne, puis sa variante pour le dev, avant de voir comment pousser tout ça sur un parc de Cloud PC via Intune.
Pour vous guider plus facilement dans cet article, voici des liens rapides :
- 1. Le principe : un réglage par intention
- 2. Étape 0 : les prérequis
- 3. Étape 1 : préparer les outils côté hôte
- 4. Étape 2 : le .wsb durci d’analyse
- 5. Étape 3 : le script de démarrage
- 6. Étape 4 : le moment de vérité
- 7. Variante : une sandbox de dev auto-provisionnée
- 8. Pousser tout ça sur un parc via Intune
- 9. Jusqu’où faire confiance ?
- 10. Récap : prérequis et pièges
1. Le principe : un réglage par intention
Pour rappel, Windows Sandbox est un environnement Windows jetable : du Hyper-V, une seule instance à la fois, calée sur le même build que l’hôte, et tout l’état part à la poubelle à la fermeture (seul un redémarrage lancé depuis l’intérieur est conservé) :
Bac à sable Windows (WSB) offre un environnement de bureau léger et isolé pour exécuter des applications en toute sécurité. Il est idéal pour tester, déboguer, explorer des fichiers inconnus et expérimenter des outils.
Les applications installées dans le bac à sable restent isolées de l’ordinateur hôte à l’aide de la virtualisation basée sur l’hyperviseur.
Source : Microsoft Learn

Vous ouvrez, vous testez, vous fermez, il ne reste rien :

En tant que machine virtuelle jetable, Bac à sable Windows garantit la persistance du redémarrage, des temps de lancement rapides et un encombrement mémoire inférieur par rapport aux machines virtuelles complètes. Sa configuration en un clic simplifie l’expérience utilisateur.
Source : Microsoft Learn
L’erreur, c’est de croire qu’il existe un seul bon réglage. En réalité, on configure la sandbox selon l’intention. Pour de l’analyse, on veut la couper du monde : réseau désactivé, entrée en lecture seule, presse-papier coupé. Pour du dev, on veut au contraire le réseau actif pour tirer les paquets. C’est le fil rouge de cet article, et ça change tout, surtout sur un Cloud PC branché sur le réseau de l’entreprise.
Le piège classique : dans Windows Sandbox, le réseau est activé par défaut :

Enabling networking can expose untrusted applications to the internal network.
Source : Windows Sandbox overview, Microsoft Learn
Microsoft recommande d’ailleurs, pour lancer une appli non fiable, exactement la posture qu’on va construire : réseau désactivé et dossier de l’application mappé en lecture seule.
2. Étape 0 : les prérequis
Avant de commencer, trois choses côté hôte :
Savoir si la fonctionnalité Windows Sandbox est déjà activée :
Get-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM

Si elle ne l’est pas encore, passez par Activer ou désactiver des fonctionnalités Windows (ou en PowerShell) :
Enable-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM -All

L’installation de la Sandbox Windows nécessite un redémarrage du poste :

Et cela prendra une quinzaine de minutes environ :

Attention, la virtualisation doit être disponible sur la machine !
Sur un Cloud PC Windows 365, ce dernier point mérite attention : Windows Sandbox y passe par la virtualisation imbriquée, qui n’est disponible que si le Cloud PC a 4 vCPU ou plus :
Pour utiliser des charges de travail basées sur la virtualisation, le Cloud PC doit répondre à ces exigences :
- PC cloud de 4 processeurs virtuels ou plus (le fait de réduire à 2 processeurs virtuels les PC cloud désactive la virtualisation imbriquée).
- Être approvisionné dans l’une des régions prises en charge pour Windows 365. (La virtualisation imbriquée n’est actuellement pas prise en charge en Afrique du Sud Nord).
- Certains utilisateurs peuvent rencontrer une baisse des performances de leur PC cloud 4 processeurs virtuels lors de l’utilisation de la virtualisation imbriquée. Pour plus d’informations sur la résolution de ces problèmes de performances.
3. Étape 1 : préparer les outils côté hôte
Créez un dossier de travail sur l’hôte, par exemple C:\Sandbox, qui servira à passer les fichiers et les scripts à la sandbox :

Puisque la sandbox d’analyse sera hors-ligne, on lui prépare tout depuis l’hôte. Je suis parti du repo mdevolde/windows-sandbox-malware, qui pose bien la mécanique, mais j’ai dû l’adapter : les scripts d’origine ne fonctionnaient pas tels quels chez moi.
Voici ma version, testée de bout en bout :
Le script preinstall.ps1 crée C:\Sandbox\install et y télécharge, via winget, six outils d’analyse : Notepad++, Sysinternals Suite, 7-Zip, x64dbg, Wireshark et PE-bear :
$currentUser = [Environment]::UserName
$dl = Join-Path -Path $env:USERPROFILE -ChildPath "Downloads"
$ProgressPreference = 'SilentlyContinue'
Write-Host "Current user: $currentUser"
$procArch = $env:PROCESSOR_ARCHITECTURE
switch -Wildcard ($procArch) {
"AMD64" { $arch = "x64" }
"x86" { $arch = "x86" }
"*ARM64*" { $arch = "arm64" }
"*ARM*" { $arch = "arm" }
default {
$arch = "x64"
Write-Warning "Unrecognized architecture: $procArch. Defaulting to x64."
}
}
Write-Host "`nDetected architecture: $arch"
# Install winget if not already installed
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host "winget is already installed. Skipping installation."
} else {
Write-Host "Downloading winget."
$release = Invoke-RestMethod https://api.github.com/repos/microsoft/winget-cli/releases/latest
$depsUrl = $release.assets | Where-Object { $_.name -eq "DesktopAppInstaller_Dependencies.zip" } | Select-Object -ExpandProperty browser_download_url
$msixUrl = $release.assets | Where-Object { $_.name -like "*.msixbundle" } | Select-Object -ExpandProperty browser_download_url
Invoke-WebRequest $depsUrl -OutFile "$dl\winget-deps.zip"
Invoke-WebRequest $msixUrl -OutFile "$dl\winget.msixbundle"
Expand-Archive "$dl\winget-deps.zip" -DestinationPath "$dl\winget-deps" -Force
Get-ChildItem "$dl\winget-deps\$arch\*.appx" | ForEach-Object {
Add-AppxPackage -Path $_.FullName
}
Add-AppxPackage -Path "$dl\winget.msixbundle"
Remove-Item "$dl\winget-deps.zip", "$dl\winget.msixbundle" -Force
Remove-Item "$dl\winget-deps" -Recurse -Force
}
New-Item -ItemType Directory -Force -Path 'C:\Sandbox\install' | Out-Null
# Telecharge les outils pour installation offline dans le bac a sable
winget download Notepad++.Notepad++ --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
winget download Microsoft.Sysinternals.Suite --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
winget download 7zip.7zip --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
winget download x64dbg.x64dbg --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
winget download WiresharkFoundation.Wireshark --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
winget download hasherezade.PE-bear --accept-source-agreements --accept-package-agreements --download-directory C:\Sandbox\install\
Write-Host "`nOK -> C:\Sandbox\install"
Get-ChildItem C:\Sandbox\install -Recurse -File | Select-Object Name, @{n='MB';e={[math]::Round($_.Length/1MB,1)}}
Lancez le script depuis votre poste local :
powershell -ExecutionPolicy Bypass -File .\scripts\preinstall.ps1

Les installeurs sont alors visibles dans le dossier suivant :

Continuons avec le fichier de configuration du premier test de la Sandbox.
4. Étape 2 : le .wsb durci d’analyse
Voici le fichier de configuration Sandbox dans le cadre d’un essai pour analyse :

Il coupe le réseau et le vGPU, désactive presse-papier, imprimante, micro et webcam, monte C:\Sandbox en lecture seule, et lance le script de préparation au démarrage. Il reprend les réglages du malware.wsb du repo mdevolde, avec deux ajouts de mon cru : le chemin vers le sous-dossier scripts, et l’option -NoExit qui garde la fenêtre PowerShell ouverte. Sans elle, la fenêtre se ferme aussitôt et vous ne voyez jamais les erreurs.
<Configuration>
<VGpu>Disable</VGpu>
<Networking>Disable</Networking>
<AudioInput>Disable</AudioInput>
<VideoInput>Disable</VideoInput>
<PrinterRedirection>Disable</PrinterRedirection>
<ClipboardRedirection>Disable</ClipboardRedirection>
<MemoryInMB>8192</MemoryInMB>
<MappedFolders>
<MappedFolder>
<HostFolder>C:\Sandbox</HostFolder>
<SandboxFolder>C:\Users\WDAGUtilityAccount\Desktop\HostShared</SandboxFolder>
<ReadOnly>true</ReadOnly>
</MappedFolder>
</MappedFolders>
<LogonCommand>
<Command>powershell.exe -NoProfile -NoExit -ExecutionPolicy Bypass -File C:\Users\WDAGUtilityAccount\Desktop\HostShared\scripts\SandboxSetup.ps1</Command>
</LogonCommand>
</Configuration>
Chaque réglage a un rôle : Networking à Disable coupe toute comm réseau (pas de C2 possible) :

ReadOnly à true fait de C:\Sandbox une entrée à sens unique :

Et couper le presse-papier ferme un canal d’exfiltration.
Le compte intégré de la sandbox s’appelle WDAGUtilityAccount, d’où le chemin du bureau en sortie :

Une variante utile : on peut laisser au contraire le presse-papier actif, pour faire glisser le fichier depuis l’hôte avant de tout couper. Deux écoles : entrée par dossier en lecture seule (plus stricte) ou par presse-papier (plus pratique). À vous de choisir selon votre niveau de paranoïa.
5. Étape 3 : le script de démarrage
Au démarrage, la LogonCommand exécute SandboxSetup.ps1 (copié dans C:\Sandbox\scripts). Ce script installe en silence les outils depuis HostShared\install, puis prépare l’environnement pour l’analyse : affichage des extensions et des fichiers cachés, activation des chemins longs, entrées de menu contextuel (ouvrir PowerShell ou l’invite de commandes ici, éditer avec Notepad++), et quelques réglages d’ergonomie.
Voici le script tournant au démarrage de la Sandbox :

Le détail complet du script SandboxSetup.ps1 est juste ici :
Start-Transcript -Path C:\SandboxLog.txt -Force
Write-Host "Setting up Windows environment (context menu, explorer options, etc.)"
# Menu contextuel ancien style
reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve | Out-Null
# Afficher les extensions
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f | Out-Null
# Afficher les fichiers caches
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "Hidden" /t REG_DWORD /d 1 /f | Out-Null
# Chemins longs
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v "LongPathsEnabled" /t REG_DWORD /d 1 /f | Out-Null
# Contournement des installs MSI tres lentes (desactive la validation WDAC / Smart App Control)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy" /v "VerifiedAndReputablePolicyState" /t REG_DWORD /d 0 /f | Out-Null
CiTool.exe --refresh --json | Out-Null
try { Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -ErrorAction Stop | Out-Null } catch {}
# Historique du presse-papier
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Clipboard" -Name "EnableClipboardHistory" -Value 1 -Type DWord -Force
# Buffer console
New-Item -Path "HKCU:\Console" -Force | Out-Null
Set-ItemProperty -Path "HKCU:\Console" -Name "ScreenBufferSize" -Value 2147418232 -Type DWord
# Fond d'ecran fixe
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\DesktopSpotlight\Settings" -Force | Out-Null
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\DesktopSpotlight\Settings" -Name "EnabledState" -Value 0 -Type DWord
Copy-Item -Path "C:\Windows\Web\Wallpaper\Windows\img0.jpg" -Destination "$env:APPDATA\Microsoft\Windows\Themes\TranscodedWallpaper" -Force
# 'Open PowerShell Here' / 'Open CMD Here'
$powershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$cmdPath = "C:\Windows\System32\cmd.exe"
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\MyPowerShell" /ve /d "Open PowerShell Here" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\MyPowerShell" /v "Icon" /t REG_SZ /d "$powershellPath,0" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\MyPowerShell\command" /ve /d "powershell.exe -noexit -command Set-Location -literalPath '%V'" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Mycmd" /ve /d "Open CMD Here" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Mycmd" /v "Icon" /t REG_SZ /d "$cmdPath,0" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Mycmd\command" /ve /d 'cmd.exe /s /k cd /d "%V"' /f | Out-Null
# Nouveau > .txt
reg add "HKEY_CLASSES_ROOT\txtfile" /ve /d "Text Document" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\.txt\ShellNew" /f | Out-Null
reg --% add "HKEY_CLASSES_ROOT\.txt\ShellNew" /v "NullFile" /t REG_SZ /d "" /f
reg add "HKEY_CLASSES_ROOT\.txt\ShellNew" /v "ItemName" /t REG_SZ /d "New Text Document" /f | Out-Null
# Nouveau > .ps1
reg add "HKEY_CLASSES_ROOT\.ps1" /ve /d "ps1file" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\ps1file" /ve /d "PowerShell Script" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\ps1file\DefaultIcon" /ve /d "%SystemRoot%\System32\imageres.dll,-5372" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\.ps1\ShellNew" /ve /d "ps1file" /f | Out-Null
reg --% add "HKEY_CLASSES_ROOT\.ps1\ShellNew" /v "NullFile" /t REG_SZ /d "" /f
reg add "HKEY_CLASSES_ROOT\.ps1\ShellNew" /v "ItemName" /t REG_SZ /d "script" /f | Out-Null
# ---------- Installation des outils (offline) ----------
Write-Host "Installing offline tools..."
$ProgressPreference = 'SilentlyContinue'
$source = "C:\Users\WDAGUtilityAccount\Desktop\HostShared\install"
$destRoot = "C:\Program Files\"
if (-not (Test-Path $source)) { Write-Error "Dossier introuvable : $source"; Stop-Transcript; return }
$currentUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
$userPathEntries = @($currentUserPath -split ';' | Where-Object { $_ -and $_.Trim() -ne "" })
# 1) Dependances .exe (VC Redist dans Dependencies\) : -Recurse indispensable
Get-ChildItem -Path $source -Filter *.exe -Recurse | ForEach-Object {
Write-Host "Installing dependency $($_.Name)"
Start-Process -FilePath $_.FullName -ArgumentList '/install','/quiet','/norestart' -Wait
}
# 2) MSI : c'est ce que winget download produit (Notepad++, 7-Zip, Wireshark)
Get-ChildItem -Path $source -Filter *.msi | ForEach-Object {
Write-Host "Installing MSI $($_.Name)"
$log = "C:\msi_" + ($_.BaseName -replace '[^\w]','_') + ".log"
$p = Start-Process msiexec.exe -ArgumentList '/i',"`"$($_.FullName)`"",'/qn','/norestart','/l*v',"`"$log`"" -Wait -PassThru
Write-Host (" exit code: " + $p.ExitCode)
}
# 3) ZIP portables (Sysinternals, x64dbg, PE-bear) -> Program Files + PATH
Get-ChildItem -Path $source -Filter *.zip | ForEach-Object {
$dest = $destRoot + $_.BaseName
$pathToAdd = $dest
Write-Host "Extracting $($_.Name) to $dest"
Expand-Archive -Path $_.FullName -DestinationPath $dest -Force
if ($dest -like "*x64dbg*") { $pathToAdd = Join-Path -Path $dest -ChildPath "release\x64" }
if ($userPathEntries -notcontains $pathToAdd) {
$userPathEntries += $pathToAdd
Write-Host "Adding to PATH: $pathToAdd"
}
}
$newUserPath = ($userPathEntries -join ';') + ';'
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
$env:Path = $newUserPath + [Environment]::GetEnvironmentVariable("Path", "Machine")
Write-Host "Done."
# ---------- Notepad++ : uniquement s'il est bien installe ----------
$notepadPlusPlusPath = (Get-Command notepad++.exe -ErrorAction SilentlyContinue).Source
if (-not $notepadPlusPlusPath -and (Test-Path "C:\Program Files\Notepad++\notepad++.exe")) {
$notepadPlusPlusPath = "C:\Program Files\Notepad++\notepad++.exe"
}
if ($notepadPlusPlusPath) {
Write-Host "Adding Notepad++ to context menu"
$nppCmd = '"{0}" -settingsDir="%appdata%" "%1"' -f $notepadPlusPlusPath
$nppOpenCmd = '"{0}" -settingsDir="%appdata%"' -f $notepadPlusPlusPath
reg add "HKEY_CLASSES_ROOT\*\shell\Edit with Notepad++" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\*\shell\Edit with Notepad++" /v "Icon" /t REG_SZ /d "$notepadPlusPlusPath,0" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\*\shell\Edit with Notepad++\command" /ve /t REG_EXPAND_SZ /d $nppCmd /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Notepad++" /ve /d "Open Notepad++" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Notepad++" /v "Icon" /t REG_SZ /d "$notepadPlusPlusPath,0" /f | Out-Null
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Notepad++\command" /ve /t REG_EXPAND_SZ /d $nppOpenCmd /f | Out-Null
cmd /c assoc .txt=txtfile | Out-Null
if (!(Test-Path 'HKLM:\SOFTWARE\Classes\txtfile\shell\open\command')) {
New-Item -Path 'HKLM:\SOFTWARE\Classes\txtfile\shell\open\command' -Force | Out-Null
}
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Classes\txtfile\shell\open\command' -Name '(Default)' -Value $nppCmd -Type ExpandString -Force
} else {
Write-Warning "Notepad++ introuvable, association et menu contextuel ignores."
}
Write-Host ""
Write-Host "=== Recap ==="
Get-ChildItem $source -Recurse -File | Select-Object Name, @{n='MB';e={[math]::Round($_.Length/1MB,1)}} | Format-Table -AutoSize
Write-Host "Log complet : C:\SandboxLog.txt"
Stop-Transcript
# Decommentez ces 2 lignes une fois le debug termine
# Stop-Process -Name explorer -Force
# Start-Process explorer.exe C:\Users\WDAGUtilityAccount\Desktop\HostShared
Vous le copiez, vous le posez dans C:\Sandbox\scripts\, et la sandbox fait le reste. Concrètement, ça donne quoi ? En quelques secondes après le démarrage, vous avez un poste d’analyse prêt, hors-ligne, avec vos outils.

Un mot sur le débogage : le Start-Transcript en tête de script écrit tout dans C:\SandboxLog.txt. En cas de souci, c’est le premier endroit à regarder. Vous y verrez d’ailleurs une ligne TerminatingError(Set-ExecutionPolicy) qui n’est pas un plantage : c’est le message habituel indiquant qu’une policy plus spécifique prime, et le script continue sans problème.

6. Étape 4 : le moment de vérité
Le moment de vérité. Vous analysez avec ce dont vous avez besoin, sans jamais auto-exécuter le payload : c’est vous qui décidez quoi lancer et quand.
Déposez l’échantillon suspect dans C:\Sandbox côté hôte :

Double-cliquez sur le .wsb :

La sandbox démarre déjà outillé et coupé du monde :

Les applications s’installent :

Et voilà !

Il ne reste qu’à travailler dessus :

Et quand vous avez fini, vous fermez la fenêtre. Tout disparaît, l’échantillon compris. Rien n’a touché votre poste, rien n’a atteint le réseau.

7. Variante : une sandbox de dev auto-provisionnée
Le même mécanisme, posture inversée. Pour du dev, on veut le réseau actif pour tirer les paquets, et un script qui installe la toolchain au démarrage. Le repo M-d3bug fournit un Sandbox_opencode.wsb qui, au logon, installe Python, Node LTS, Git et Windows Terminal, puis opencode via npm.
Microsoft propose aussi de son côté un exemple officiel d’installation de VS Code au lancement.
J’ai retenu la seconde piste, et pour une bonne raison : je voulais la même approche hors-ligne que pour l’analyse. Or opencode passe par npm, qui a besoin du réseau pour aller chercher son paquet. VS Code, lui, existe en installeur autonome, donc on peut le stager sur l’hôte et l’installer sans la moindre connexion. Le principe reste le même que pour la sandbox d’analyse : tout ce qui touche à Internet se fait côté hôte, une bonne fois.
Voici le fichier de préinstall :
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ProgressPreference = 'SilentlyContinue'
$installDir = 'C:\SandboxDev\install'
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
Write-Host 'Resolution des versions...'
# Python (dernier amd64 stable)
$listing = Invoke-WebRequest 'https://www.python.org/ftp/python/' -UseBasicParsing
$py = $null
foreach ($v in ([regex]::Matches($listing.Content,'\d+\.\d+\.\d+/') |
ForEach-Object { [Version]($_.Value -replace '/$','') } |
Sort-Object -Descending | Select-Object -Unique)) {
$u = "https://www.python.org/ftp/python/$v/python-$v-amd64.exe"
try { if ((Invoke-WebRequest $u -Method Head -UseBasicParsing -ErrorAction Stop).StatusCode -eq 200) { $py=$u; break } } catch {}
}
if (-not $py) { throw 'Python introuvable.' }
# Git
$gitRel = Invoke-RestMethod 'https://api.github.com/repos/git-for-windows/git/releases/latest' -Headers @{'User-Agent'='Mozilla/5.0'}
$git = ($gitRel.assets | Where-Object {$_.name -match 'Git-.*-64-bit\.exe'} | Select-Object -First 1).browser_download_url
# Windows Terminal + deps
$wtRel = Invoke-RestMethod 'https://api.github.com/repos/microsoft/terminal/releases/latest' -Headers @{'User-Agent'='Mozilla/5.0'}
$wt = ($wtRel.assets | Where-Object {$_.name -match '^Microsoft\.WindowsTerminal_\d+\.\d+\.\d+\.\d+_8wekyb3d8bbwe\.msixbundle$'} | Select-Object -First 1).browser_download_url
$xamlRel = Invoke-RestMethod 'https://api.github.com/repos/microsoft/microsoft-ui-xaml/releases?per_page=100' -Headers @{'User-Agent'='Mozilla/5.0'}
$xaml = $null
foreach ($r in $xamlRel) {
if ($r.tag_name -notmatch '^v2\.8\.') { continue }
$a = $r.assets | Where-Object {$_.name -eq 'Microsoft.UI.Xaml.2.8.x64.appx'} | Select-Object -First 1
if ($a) { $xaml = $a.browser_download_url; break }
}
$vclibs = 'https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx'
# VS Code (installeur autonome user-setup x64)
$vscode = 'https://update.code.visualstudio.com/latest/win32-x64-user/stable'
$dl = @(
@{Url=$py; Dest="$installDir\python-installer.exe"},
@{Url=$git; Dest="$installDir\git-installer.exe"},
@{Url=$vscode; Dest="$installDir\vscode-setup.exe"},
@{Url=$wt; Dest="$installDir\wt.msixbundle"},
@{Url=$vclibs; Dest="$installDir\vclibs.appx"},
@{Url=$xaml; Dest="$installDir\xaml.appx"}
)
foreach ($d in $dl) {
Write-Host (" " + (Split-Path $d.Dest -Leaf))
$wc = New-Object System.Net.WebClient
$wc.Headers.Add('User-Agent','Mozilla/5.0')
$wc.DownloadFile($d.Url, $d.Dest)
}
Write-Host "OK -> $installDir"
Je télécharge localement les différents installeurs :
powershell -ExecutionPolicy Bypass -File .\DevPreinstall.ps1
C:\SandboxDev\DevSetup.ps1 (install offline, tourne dans la sandbox) :
$src = 'C:\Users\WDAGUtilityAccount\Desktop\SandboxDev\install' # mappe lecture seule
$work = 'C:\SandboxSetup'
New-Item -ItemType Directory -Force -Path $work | Out-Null
Copy-Item "$src\*" $work -Force
# WDAC / Smart App Control coupe pour accelerer les installs
Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -Command Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\CI\Policy -Name VerifiedAndReputablePolicyState -Value 0; echo $null | CiTool.exe -r' -Verb RunAs -WindowStyle Hidden
Start-Sleep -Seconds 3
Set-Location $work
Write-Host 'Python...'
Start-Process "$work\python-installer.exe" -ArgumentList '/quiet','InstallAllUsers=1','PrependPath=1','Include_test=0','SimpleInstall=1' -Wait
Write-Host 'Git...'
Start-Process "$work\git-installer.exe" -ArgumentList '/VERYSILENT','/NORESTART' -Wait
Write-Host 'Windows Terminal...'
Add-AppxPackage -Path "$work\vclibs.appx" -ErrorAction SilentlyContinue
Add-AppxPackage -Path "$work\xaml.appx" -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
Add-AppxPackage -Path "$work\wt.msixbundle" -ErrorAction SilentlyContinue
Write-Host 'VS Code...'
Start-Process "$work\vscode-setup.exe" -ArgumentList '/verysilent','/suppressmsgboxes','/norestart','/mergetasks=!runcode' -Wait
Write-Host ''
Write-Host 'Termine. Environnement de dev pret (offline).'

8. Pousser tout ça sur un parc via Intune
Jusqu’ici, tout s’est joué sur une seule machine, la vôtre. Sur un parc, la question change : comment rendre Windows Sandbox disponible sur des dizaines de postes ou de Cloud PC ?
Bonne nouvelle, il n’y a rien à déployer. Windows Sandbox n’est pas une application à installer, c’est une fonctionnalité déjà présente dans Windows qu’il suffit d’activer : Containers-DisposableClientVM. La méthode de référence est celle de Peter van der Woude : un script PowerShell Intune, exécuté en contexte SYSTEM, assigné aux appareils, avec un redémarrage pour finaliser.
Enable-WindowsOptionalFeature -Online -FeatureName "Containers-DisposableClientVM" -All -NoRestart

Avant le déploiement du script :

Après le déploiement du script :

Il ne reste qu’à redémarrer le Cloud PC :
Autre usage Intune, plus discutable : enrôler une Sandbox comme device de test jetable pour valider un Win32 ou une remédiation, comme le montre Damien Van Robaeys. Ça marche, mais la sandbox s’efface à la fermeture : vous devez ré-enrôler à chaque lancement, et chaque cycle laisse un objet appareil fantôme et ingérable dans le tenant. Pratique pour un lab, salissant pour l’hygiène de production.

Quelques minutes plus tard, la sandbox devient visible sur Intune :

9. Jusqu’où faire confiance ?
Soyons honnêtes sur les limites. Windows Sandbox, c’est de l’isolation renforcée, pas un airgap.
- Une évasion d’hyperviseur reste théoriquement possible : la sandbox partage le build et l’hyperviseur de l’hôte.
- Certains malwares détectent qu’ils sont en sandbox et restent dormants. « Il ne s’est rien passé » ne prouve donc pas l’innocuité.
- Réseau coupé, vous perdez l’analyse dynamique (pas d’observation des appels réseau).
- Désactiver Smart App Control pour gagner du temps, c’est baisser une protection réelle.
10. Récap : prérequis et pièges
| Élément | Ce qu’il faut | Le piège à éviter |
|---|---|---|
| vCPU (Cloud PC) | 4 vCPU ou plus | Repasser à 2 vCPU désactive la virtualisation imbriquée |
| Type de Cloud PC | Non-GPU | Un Cloud PC GPU ne fait tourner ni Sandbox, ni WSL, ni Hyper-V |
| Région | Une région supportée | Non supporté en South Africa North |
| Réseau (analyse) | Networking sur Disable | Réseau activé par défaut, exposé au réseau interne |
| Réseau (dev) | Networking sur Enable | Télécharge et exécute des installeurs à chaque lancement |
| Activation Intune | Ciblage GPU / 2 vCPU exclus | La fonctionnalité s’active même là où elle ne tourne pas |
| Enrôlement Intune | Réservé au lab | Ré-enrôlement à chaque lancement, devices fantômes dans le tenant |
Conclusion
Voilà, en quatre étapes plus une variante, vous avez une sandbox d’analyse jetable et durcie, une sandbox de dev auto-provisionnée, et de quoi déployer proprement la fonctionnalité sur un parc de Cloud PC. Concrètement, ce que vous y gagnez : ouvrir un truc pas net en isolation, en trente secondes, puis tout jeter, sans jamais toucher votre poste ni le réseau.
Les pièges à retenir :
- Réseau activé par défaut : pour l’analyse, coupez-le explicitement.
- Un réglage par intention : analyse hors-ligne, dev en ligne, ne les confondez jamais.
- Sur Cloud PC : 4 vCPU minimum, région supportée, jamais de GPU.
- Via Intune, la fonctionnalité s’active même là où elle ne tourne pas : ciblez.
- La sandbox n’est pas un labo d’analyse de malware ciblé.
Foncez tester : préparez C:\Sandbox, récupérez les scripts, collez le .wsb d’analyse, et lancez. Une fois le réflexe pris, on n’ouvre plus jamais un fichier douteux autrement.
