diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b0864a..31b9e90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [2.2.3] - 2025-01-07 + +### 🔨 Bugfix Release + +**Critical bugfix for Restore Mode manual module selection.** + +### 🔨 Fixed + +**Restore Mode Module Selection Crash (Critical)** +- Fixed: Selecting `[M] Restore only SELECTED modules` and entering any module number caused a fatal PowerShell error +- Root cause: `.Split(',', ';', ' ')` triggered wrong .NET overload `Split(string, Int32)`, interpreting `;` as count parameter +- Fix: Replaced with native PowerShell `-split '[,; ]'` operator +- Impact: Manual module selection in Restore workflow now works correctly +- Reported by: KatCat2 + +--- + ## [2.2.2] - 2025-12-22 ### 🚀 Performance Release diff --git a/Core/Config.ps1 b/Core/Config.ps1 index 263d2ca..be9c143 100644 --- a/Core/Config.ps1 +++ b/Core/Config.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -79,104 +79,104 @@ function New-DefaultConfig { ) $defaultConfig = @{ - version = "2.2.2" + version = "2.2.3" modules = @{ SecurityBaseline = @{ - enabled = $true - priority = 1 - status = "IMPLEMENTED" + enabled = $true + priority = 1 + status = "IMPLEMENTED" bitLockerUSBEnforcement = $false } - ASR = @{ - enabled = $true - priority = 2 - status = "IMPLEMENTED" - usesManagementTools = $false - allowNewSoftware = $false + ASR = @{ + enabled = $true + priority = 2 + status = "IMPLEMENTED" + usesManagementTools = $false + allowNewSoftware = $false continueWithoutCloud = $true } - DNS = @{ - enabled = $true + DNS = @{ + enabled = $true priority = 3 - status = "IMPLEMENTED" + status = "IMPLEMENTED" provider = "Quad9" - dohMode = "REQUIRE" + dohMode = "REQUIRE" } - Privacy = @{ - enabled = $true - priority = 4 - status = "IMPLEMENTED" - mode = "MSRecommended" + Privacy = @{ + enabled = $true + priority = 4 + status = "IMPLEMENTED" + mode = "MSRecommended" disableCloudClipboard = $true - removeBloatware = $true + removeBloatware = $true } - AntiAI = @{ - enabled = $true - priority = 5 - status = "IMPLEMENTED" + AntiAI = @{ + enabled = $true + priority = 5 + status = "IMPLEMENTED" description = "Disable all Windows 11 AI features (Recall, Copilot, Paint AI, etc.)" } - EdgeHardening = @{ - enabled = $true - priority = 6 - status = "IMPLEMENTED" - description = "Microsoft Edge v139 Security Baseline: 24 security policies" + EdgeHardening = @{ + enabled = $true + priority = 6 + status = "IMPLEMENTED" + description = "Microsoft Edge v139 Security Baseline: 24 security policies" allowExtensions = $true - version = "2.2.2" - baseline = "Edge v139" - policies = 24 - features = @{ - smartscreen_enforcement = $true - site_isolation = $true - ssl_error_blocking = $true - extension_blocklist = $true - ie_mode_restrictions = $true - spectre_mitigations = $true - application_encryption = $true + version = "2.2.3" + baseline = "Edge v139" + policies = 24 + features = @{ + smartscreen_enforcement = $true + site_isolation = $true + ssl_error_blocking = $true + extension_blocklist = $true + ie_mode_restrictions = $true + spectre_mitigations = $true + application_encryption = $true auth_scheme_restrictions = $true } } AdvancedSecurity = @{ - enabled = $true - priority = 7 - status = "IMPLEMENTED" - description = "Advanced Security hardening beyond MS Baseline" - securityProfile = "Balanced" - disableRDP = $true - forceAdminShares = $false - disableUPnP = $true - disableWirelessDisplay = $false + enabled = $true + priority = 7 + status = "IMPLEMENTED" + description = "Advanced Security hardening beyond MS Baseline" + securityProfile = "Balanced" + disableRDP = $true + forceAdminShares = $false + disableUPnP = $true + disableWirelessDisplay = $false disableDiscoveryProtocols = $true - disableIPv6 = $false - version = "2.2.2" - policies = 50 - features = @{ - rdp_hardening = $true - wdigest_protection = $true - admin_shares_disable = $true - risky_ports_closure = $true - risky_services_stop = $true - legacy_tls_disable = $true - wpad_disable = $true - powershell_v2_removal = $true - srp_lnk_protection = $true - windows_update_config = $true - finger_protocol_block = $true - wireless_display_security = $true + disableIPv6 = $false + version = "2.2.3" + policies = 50 + features = @{ + rdp_hardening = $true + wdigest_protection = $true + admin_shares_disable = $true + risky_ports_closure = $true + risky_services_stop = $true + legacy_tls_disable = $true + wpad_disable = $true + powershell_v2_removal = $true + srp_lnk_protection = $true + windows_update_config = $true + finger_protocol_block = $true + wireless_display_security = $true discovery_protocols_security = $true - firewall_shields_up = $true - ipv6_disable = $true + firewall_shields_up = $true + ipv6_disable = $true } - profiles = @("Balanced", "Enterprise", "Maximum") + profiles = @("Balanced", "Enterprise", "Maximum") } } options = @{ - dryRun = $false - createBackup = $true + dryRun = $false + createBackup = $true verboseLogging = $true - autoReboot = $false + autoReboot = $false nonInteractive = $false - autoConfirm = $false + autoConfirm = $false } } @@ -434,7 +434,7 @@ function Get-EnabledModules { # Check if module is actually implemented if (Test-ModuleAvailability -ModuleName $moduleName) { $enabledModules += [PSCustomObject]@{ - Name = $moduleName + Name = $moduleName Priority = $moduleConfig.priority } } diff --git a/Core/Framework.ps1 b/Core/Framework.ps1 index 8e28443..352f248 100644 --- a/Core/Framework.ps1 +++ b/Core/Framework.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ .EXAMPLE @@ -24,7 +24,7 @@ # All configuration comes from config.json via Initialize-Config. # Script-level variables -$script:FrameworkVersion = "2.2.2" +$script:FrameworkVersion = "2.2.3" $script:FrameworkRoot = Split-Path -Parent $PSScriptRoot $script:ExecutionStartTime = Get-Date @@ -409,8 +409,8 @@ function Invoke-Hardening { else { # CLI mode: Auto-detect session type based on module count $autoSessionType = if ($modulesToExecute.Count -ge 7) { "wizard" } - elseif ($modulesToExecute.Count -eq 1) { "advanced" } - else { "manual" } + elseif ($modulesToExecute.Count -eq 1) { "advanced" } + else { "manual" } Set-SessionType -SessionType $autoSessionType Write-Log -Level DEBUG -Message "Session type auto-detected: $autoSessionType (based on $($modulesToExecute.Count) modules)" -Module "Framework" } @@ -451,7 +451,7 @@ function Invoke-Hardening { $ruleCount = $ruleIds.Count $preFrameworkSnapshot = @{ - ASR = @{ + ASR = @{ RuleIds = $ruleIds RuleActions = $ruleActions SnapshotDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" diff --git a/Core/Logger.ps1 b/Core/Logger.ps1 index e0b2061..ee15c75 100644 --- a/Core/Logger.ps1 +++ b/Core/Logger.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -26,10 +26,10 @@ enum LogLevel { # NOTE: Must use Get-Variable to check existence (direct access fails in Strict Mode) if (-not (Get-Variable -Name 'LoggerConfig' -Scope Global -ErrorAction SilentlyContinue)) { $global:LoggerConfig = @{ - LogFilePath = "" - MinimumLevel = [LogLevel]::INFO - EnableConsole = $true - EnableFile = $true + LogFilePath = "" + MinimumLevel = [LogLevel]::INFO + EnableConsole = $true + EnableFile = $true TimestampFormat = "yyyy-MM-dd HH:mm:ss" } } @@ -193,10 +193,10 @@ function Write-Log { # Write to console with color coding (suppress DEBUG-level on console) if ($global:LoggerConfig.EnableConsole -and $Level -ge [LogLevel]::INFO) { $consoleColor = switch ($Level) { - ([LogLevel]::DEBUG) { "Gray" } - ([LogLevel]::INFO) { "White" } + ([LogLevel]::DEBUG) { "Gray" } + ([LogLevel]::INFO) { "White" } ([LogLevel]::WARNING) { "Yellow" } - ([LogLevel]::ERROR) { "Red" } + ([LogLevel]::ERROR) { "Red" } ([LogLevel]::SUCCESS) { "Green" } default { "White" } } @@ -245,15 +245,15 @@ function Get-ErrorContext { ) $context = @{ - Message = "" - Exception = "" - Category = "" + Message = "" + Exception = "" + Category = "" TargetObject = "" - ScriptName = "" - LineNumber = 0 - Command = "" - StackTrace = "" - Summary = "" + ScriptName = "" + LineNumber = 0 + Command = "" + StackTrace = "" + Summary = "" } if ($null -eq $ErrorRecord) { @@ -271,13 +271,15 @@ function Get-ErrorContext { if ($ErrorRecord.InvocationInfo) { $context.ScriptName = if ($ErrorRecord.InvocationInfo.ScriptName) { Split-Path -Leaf $ErrorRecord.InvocationInfo.ScriptName - } else { + } + else { "N/A" } $context.LineNumber = $ErrorRecord.InvocationInfo.ScriptLineNumber $context.Command = if ($ErrorRecord.InvocationInfo.MyCommand) { $ErrorRecord.InvocationInfo.MyCommand.Name - } else { + } + else { "N/A" } } diff --git a/Core/NonInteractive.ps1 b/Core/NonInteractive.ps1 index 9cf5a28..26ba39b 100644 --- a/Core/NonInteractive.ps1 +++ b/Core/NonInteractive.ps1 @@ -12,7 +12,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Usage in modules: 1. Call Test-NonInteractiveMode to check if prompts should be skipped @@ -194,7 +194,8 @@ function Write-NonInteractiveDecision { $message = if ($null -ne $Value) { "[GUI] $Decision : $Value" - } else { + } + else { "[GUI] $Decision" } diff --git a/Core/Rollback.ps1 b/Core/Rollback.ps1 index e9867c9..5baea6d 100644 --- a/Core/Rollback.ps1 +++ b/Core/Rollback.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -64,7 +64,7 @@ function Initialize-BackupSystem { displayName = "" # Auto-generated based on modules sessionType = "unknown" # wizard | advanced | manual timestamp = Get-Date -Format "o" - frameworkVersion = "2.2.2" + frameworkVersion = "2.2.3" modules = @() totalItems = 0 restorable = $true @@ -116,13 +116,13 @@ function Update-SessionDisplayName { # Calculate ACTUAL settings count (not backup items!) # Each module applies a specific number of settings (Paranoid mode = max): $settingsPerModule = @{ - "SecurityBaseline" = 425 # 335 Registry + 67 Security Template + 23 Audit - "ASR" = 19 # 19 ASR Rules - "DNS" = 5 # 5 DNS Settings - "Privacy" = 78 # 54 Registry (MSRecommended) + 24 Bloatware - "AntiAI" = 32 # 32 Registry Policies (15 features) - "EdgeHardening" = 24 # 24 Edge Policies (22-23 applied depending on extensions) - "AdvancedSecurity" = 50 # 50 Advanced Settings (15 features incl. Discovery Protocols + IPv6) + "SecurityBaseline" = 425 # 335 Registry + 67 Security Template + 23 Audit + "ASR" = 19 # 19 ASR Rules + "DNS" = 5 # 5 DNS Settings + "Privacy" = 78 # 54 Registry (MSRecommended) + 24 Bloatware + "AntiAI" = 32 # 32 Registry Policies (15 features) + "EdgeHardening" = 24 # 24 Edge Policies (22-23 applied depending on extensions) + "AdvancedSecurity" = 50 # 50 Advanced Settings (15 features incl. Discovery Protocols + IPv6) } $totalSettings = 0 @@ -382,10 +382,10 @@ function Backup-RegistryKey { try { $emptyMarker = @{ - KeyPath = $KeyPath + KeyPath = $KeyPath BackupDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" - State = "NotExisted" - Message = "Registry key did not exist before hardening - must be deleted during restore" + State = "NotExisted" + Message = "Registry key did not exist before hardening - must be deleted during restore" } | ConvertTo-Json $markerFile = Join-Path $backupFolder "$safeBackupName`_EMPTY.json" @@ -935,10 +935,10 @@ function Restore-FromBackup { try { # Convert reg.exe path to PowerShell path $psKeyPath = $keyPathToRestore -replace 'HKEY_LOCAL_MACHINE', 'HKLM:' ` - -replace 'HKEY_CURRENT_USER', 'HKCU:' ` - -replace 'HKEY_CLASSES_ROOT', 'HKCR:' ` - -replace 'HKEY_USERS', 'HKU:' ` - -replace 'HKEY_CURRENT_CONFIG', 'HKCC:' + -replace 'HKEY_CURRENT_USER', 'HKCU:' ` + -replace 'HKEY_CLASSES_ROOT', 'HKCR:' ` + -replace 'HKEY_USERS', 'HKU:' ` + -replace 'HKEY_CURRENT_CONFIG', 'HKCC:' if (Test-Path $psKeyPath) { Write-Log -Level INFO -Message "Deleting existing protected key: $psKeyPath before re-import." -Module "Rollback" @@ -1106,7 +1106,8 @@ function Invoke-RestoreRebootPrompt { Write-Host "" if ($NoReboot) { Write-Host "[!] NoReboot specified - reboot prompt skipped" -ForegroundColor Yellow - } else { + } + else { Write-Host "[!] Running in NonInteractive mode - reboot prompt skipped" -ForegroundColor Yellow } Write-Host " Please reboot manually to complete the restore." -ForegroundColor Gray @@ -1421,7 +1422,8 @@ function Restore-Session { Write-RestoreLog -Level INFO -Message "Session Path: $SessionPath" if ($ModuleNames) { Write-RestoreLog -Level INFO -Message "Specific Modules: $($ModuleNames -join ', ')" - } else { + } + else { Write-RestoreLog -Level INFO -Message "Restoring: ALL modules" } Write-RestoreLog -Level INFO -Message "========================================" @@ -1849,7 +1851,7 @@ function Restore-Session { for ($i = 0; $i -lt $preFramework.ASR.RuleIds.Count; $i++) { if ($preFramework.ASR.RuleActions[$i] -ne 0) { $asrRulesToRestore += @{ - GUID = $preFramework.ASR.RuleIds[$i] + GUID = $preFramework.ASR.RuleIds[$i] Action = $preFramework.ASR.RuleActions[$i] } } @@ -1892,8 +1894,8 @@ function Restore-Session { $ruleActions = $asrRulesToRestore | ForEach-Object { $_.Action } Set-MpPreference -AttackSurfaceReductionRules_Ids $ruleIds ` - -AttackSurfaceReductionRules_Actions $ruleActions ` - -ErrorAction Stop + -AttackSurfaceReductionRules_Actions $ruleActions ` + -ErrorAction Stop $sourceDesc = if ($usePreFramework) { "PreFramework snapshot (TRUE pre-hardening)" } else { "ASR_ActiveConfiguration.json" } Write-Log -Level SUCCESS -Message "ASR rules restored via Set-MpPreference ($($asrRulesToRestore.Count) active rules from $sourceDesc)" -Module "Rollback" @@ -1961,7 +1963,8 @@ function Restore-Session { Write-Log -Level SUCCESS -Message "Explorer Advanced settings restored via PowerShell" -Module "Rollback" } } - } catch { + } + catch { Write-Log -Level WARNING -Message "PowerShell-based Explorer restore failed: $($_.Exception.Message)" -Module "Rollback" } } @@ -1985,10 +1988,10 @@ function Restore-Session { } $regType = switch ($entry.Type) { - "DWord" { "DWord" } - "String" { "String" } + "DWord" { "DWord" } + "String" { "String" } "MultiString" { "MultiString" } - default { "String" } + default { "String" } } $existing = Get-ItemProperty -Path $keyPath -Name $entry.Name -ErrorAction SilentlyContinue @@ -2227,13 +2230,13 @@ function Restore-Session { } $regType = switch ($entry.Type) { - "DWord" { "DWord" } - "String" { "String" } + "DWord" { "DWord" } + "String" { "String" } "MultiString" { "MultiString" } "ExpandString" { "ExpandString" } - "Binary" { "Binary" } - "QWord" { "QWord" } - default { "String" } + "Binary" { "Binary" } + "QWord" { "QWord" } + default { "String" } } New-ItemProperty -Path $entry.Path -Name $entry.Name -Value $entry.Value -PropertyType $regType -Force -ErrorAction Stop | Out-Null @@ -2295,7 +2298,7 @@ function Restore-Session { "HKCU:\Software\Microsoft\Windows\CurrentVersion\SystemSettings\AccountNotifications", "HKCU:\Software\Microsoft\Windows\CurrentVersion\UserProfileEngagement", "HKCU:\SOFTWARE\Microsoft\Personalization\Settings", - # NEW: Input Personalization Settings (v2.2.2 - FIX missing HKCU restore) + # NEW: Input Personalization Settings (v2.2.3 - FIX missing HKCU restore) "HKCU:\SOFTWARE\Microsoft\InputPersonalization", "HKCU:\SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore", "HKCU:\Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\appDiagnostics" @@ -2312,7 +2315,8 @@ function Restore-Session { Remove-ItemProperty -Path $keyPath -Name $prop -ErrorAction SilentlyContinue } } - } catch { + } + catch { Write-Log -Level DEBUG -Message "Could not clear $keyPath : $_" -Module "Rollback" } } @@ -2329,12 +2333,12 @@ function Restore-Session { } $regType = switch ($entry.Type) { - "DWord" { "DWord" } - "String" { "String" } + "DWord" { "DWord" } + "String" { "String" } "MultiString" { "MultiString" } "ExpandString" { "ExpandString" } - "Binary" { "Binary" } - default { "String" } + "Binary" { "Binary" } + default { "String" } } New-ItemProperty -Path $entry.Path -Name $entry.Name -Value $entry.Value -PropertyType $regType -Force -ErrorAction Stop | Out-Null @@ -2512,13 +2516,13 @@ function Restore-Session { } $regType = switch ($entry.Type) { - "DWord" { "DWord" } - "String" { "String" } + "DWord" { "DWord" } + "String" { "String" } "MultiString" { "MultiString" } "ExpandString" { "ExpandString" } - "Binary" { "Binary" } - "QWord" { "QWord" } - default { "String" } + "Binary" { "Binary" } + "QWord" { "QWord" } + default { "String" } } New-ItemProperty -Path $entry.Path -Name $entry.Name -Value $entry.Value -PropertyType $regType -Force -ErrorAction Stop | Out-Null @@ -2726,7 +2730,8 @@ function Restore-Session { Write-Host " All security settings have been reverted to backup state" -ForegroundColor White Write-Host " Modules restored: $($reversedModules.Count) | Total items: $($manifest.totalItems)" -ForegroundColor Gray Write-Host "" - } else { + } + else { Write-Host "" Write-Host " RESTORE COMPLETED WITH ISSUES " -ForegroundColor Yellow Write-Host "" diff --git a/Core/Validator.ps1 b/Core/Validator.ps1 index df69127..2319f25 100644 --- a/Core/Validator.ps1 +++ b/Core/Validator.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -27,9 +27,9 @@ function Test-Prerequisites { Write-Log -Level INFO -Message "Starting prerequisite validation" -Module "Validator" $result = [PSCustomObject]@{ - Success = $true - Errors = @() - Warnings = @() + Success = $true + Errors = @() + Warnings = @() SystemInfo = $null } @@ -133,11 +133,11 @@ function Get-WindowsVersion { } return [PSCustomObject]@{ - Version = $versionName - BuildNumber = $buildNumber - IsWindows11 = $isWindows11 - IsSupported = $isSupported - Edition = $os.Caption + Version = $versionName + BuildNumber = $buildNumber + IsWindows11 = $isWindows11 + IsSupported = $isSupported + Edition = $os.Caption Architecture = $os.OSArchitecture } } @@ -200,26 +200,26 @@ function Test-TPMAvailable { if ($null -eq $tpm) { return [PSCustomObject]@{ - Present = $false - Version = "N/A" - Enabled = $false + Present = $false + Version = "N/A" + Enabled = $false Activated = $false } } return [PSCustomObject]@{ - Present = $tpm.TpmPresent - Version = if ($tpm.ManufacturerVersion) { $tpm.ManufacturerVersion } else { "2.0" } - Enabled = $tpm.TpmEnabled + Present = $tpm.TpmPresent + Version = if ($tpm.ManufacturerVersion) { $tpm.ManufacturerVersion } else { "2.0" } + Enabled = $tpm.TpmEnabled Activated = $tpm.TpmActivated } } catch { Write-Log -Level WARNING -Message "Unable to check TPM status: $_" -Module "Validator" return [PSCustomObject]@{ - Present = $false - Version = "Unknown" - Enabled = $false + Present = $false + Version = "Unknown" + Enabled = $false Activated = $false } } @@ -294,14 +294,14 @@ function Get-SystemInfo { $internet = Test-InternetConnectivity return [PSCustomObject]@{ - OS = $osInfo - TPM = $tpmInfo - SecureBoot = $secureBoot - Virtualization = $virtualization - IsAdministrator = $isAdmin + OS = $osInfo + TPM = $tpmInfo + SecureBoot = $secureBoot + Virtualization = $virtualization + IsAdministrator = $isAdmin DiskSpaceAvailable = $diskSpace - InternetConnected = $internet - PowerShellVersion = $PSVersionTable.PSVersion.ToString() + InternetConnected = $internet + PowerShellVersion = $PSVersionTable.PSVersion.ToString() } } @@ -332,9 +332,9 @@ function Test-DomainJoined { $result = [PSCustomObject]@{ IsDomainJoined = $isDomainJoined - DomainName = if ($isDomainJoined) { $computerSystem.Domain } else { "N/A" } - Workgroup = if (-not $isDomainJoined) { $computerSystem.Workgroup } else { "N/A" } - UserConfirmed = $false + DomainName = if ($isDomainJoined) { $computerSystem.Domain } else { "N/A" } + Workgroup = if (-not $isDomainJoined) { $computerSystem.Workgroup } else { "N/A" } + UserConfirmed = $false } if ($isDomainJoined) { @@ -384,9 +384,9 @@ function Test-DomainJoined { Write-Log -Level ERROR -Message "Failed to check domain status: $_" -Module "Validator" -Exception $_.Exception return [PSCustomObject]@{ IsDomainJoined = $false - DomainName = "Error" - Workgroup = "Error" - UserConfirmed = $false + DomainName = "Error" + Workgroup = "Error" + UserConfirmed = $false } } } @@ -416,7 +416,7 @@ function Confirm-SystemBackup { Write-Log -Level INFO -Message "Backup recommendation: non-interactive confirmation (no prompt shown)" -Module "Validator" $result = [PSCustomObject]@{ - UserConfirmed = $true + UserConfirmed = $true BackupRecommended = $true } diff --git a/Modules/ASR/ASR.psd1 b/Modules/ASR/ASR.psd1 index 0484784..db4391f 100644 --- a/Modules/ASR/ASR.psd1 +++ b/Modules/ASR/ASR.psd1 @@ -1,31 +1,31 @@ @{ - RootModule = 'ASR.psm1' - ModuleVersion = '2.2.2' - GUID = 'b2c3d4e5-f6a7-8901-bcde-f23456789012' - Author = 'NexusOne23' - CompanyName = 'Open Source Project' - Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' - Description = 'Attack Surface Reduction (ASR) - All 19 Microsoft Defender ASR rules in Block mode for maximum protection against modern threats' + RootModule = 'ASR.psm1' + ModuleVersion = '2.2.3' + GUID = 'b2c3d4e5-f6a7-8901-bcde-f23456789012' + Author = 'NexusOne23' + CompanyName = 'Open Source Project' + Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' + Description = 'Attack Surface Reduction (ASR) - All 19 Microsoft Defender ASR rules in Block mode for maximum protection against modern threats' PowerShellVersion = '5.1' - RequiredModules = @() + RequiredModules = @() FunctionsToExport = @( 'Invoke-ASRRules' ) - CmdletsToExport = @() + CmdletsToExport = @() VariablesToExport = @() - AliasesToExport = @() + AliasesToExport = @() - PrivateData = @{ + PrivateData = @{ PSData = @{ - Tags = @('Security', 'ASR', 'AttackSurfaceReduction', 'Defender', 'Windows11', 'Ransomware') - LicenseUri = '' - ProjectUri = '' + Tags = @('Security', 'ASR', 'AttackSurfaceReduction', 'Defender', 'Windows11', 'Ransomware') + LicenseUri = '' + ProjectUri = '' ReleaseNotes = @" -v2.2.2 - Production Release +v2.2.3 - Production Release - All 19 ASR rules implementation - Hybrid approach: Registry backup + Set-MpPreference application - SCCM/Configuration Manager detection diff --git a/Modules/ASR/ASR.psm1 b/Modules/ASR/ASR.psm1 index fbaa557..642924f 100644 --- a/Modules/ASR/ASR.psm1 +++ b/Modules/ASR/ASR.psm1 @@ -11,7 +11,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges, Windows Defender #> diff --git a/Modules/AdvancedSecurity/AdvancedSecurity.psd1 b/Modules/AdvancedSecurity/AdvancedSecurity.psd1 index 0c1c8a9..d12bf76 100644 --- a/Modules/AdvancedSecurity/AdvancedSecurity.psd1 +++ b/Modules/AdvancedSecurity/AdvancedSecurity.psd1 @@ -2,7 +2,7 @@ # Module manifest for AdvancedSecurity # Version - ModuleVersion = '2.2.2' + ModuleVersion = '2.2.3' # Unique ID GUID = 'e7f5a3d2-8c9b-4f1e-a6d3-9b2c8f4e5a1d' @@ -48,7 +48,7 @@ LicenseUri = '' ProjectUri = '' ReleaseNotes = @' -v2.2.2 (2025-12-08) +v2.2.3 (2025-12-08) - Production release of AdvancedSecurity module - 49 advanced hardening settings implemented (was 36) - NEW: Wireless Display (Miracast) security hardening diff --git a/Modules/AdvancedSecurity/AdvancedSecurity.psm1 b/Modules/AdvancedSecurity/AdvancedSecurity.psm1 index 0df4d65..1ded715 100644 --- a/Modules/AdvancedSecurity/AdvancedSecurity.psm1 +++ b/Modules/AdvancedSecurity/AdvancedSecurity.psm1 @@ -1,5 +1,5 @@ # AdvancedSecurity Module Loader -# Version: 2.2.2 +# Version: 2.2.3 # Description: Advanced Security Hardening - Beyond Microsoft Security Baseline # Get module path diff --git a/Modules/AntiAI/AntiAI.psd1 b/Modules/AntiAI/AntiAI.psd1 index a96fdd9..47dc6e7 100644 --- a/Modules/AntiAI/AntiAI.psd1 +++ b/Modules/AntiAI/AntiAI.psd1 @@ -1,21 +1,21 @@ @{ - RootModule = 'AntiAI.psm1' - ModuleVersion = '2.2.2' - GUID = 'f8e9d7c6-5b4a-3c2d-1e0f-9a8b7c6d5e4f' - Author = 'NexusOne23' - CompanyName = 'Open Source Project' - Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' - Description = 'Comprehensive Windows 11 AI deactivation - Disables all 15 AI features using official Microsoft policies (Recall, Copilot, Paint AI, Notepad AI, Click to Do, Settings Agent, etc.). Maximum compliance mode with enterprise-grade Recall protection.' + RootModule = 'AntiAI.psm1' + ModuleVersion = '2.2.3' + GUID = 'f8e9d7c6-5b4a-3c2d-1e0f-9a8b7c6d5e4f' + Author = 'NexusOne23' + CompanyName = 'Open Source Project' + Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' + Description = 'Comprehensive Windows 11 AI deactivation - Disables all 15 AI features using official Microsoft policies (Recall, Copilot, Paint AI, Notepad AI, Click to Do, Settings Agent, etc.). Maximum compliance mode with enterprise-grade Recall protection.' PowerShellVersion = '5.1' FunctionsToExport = @( 'Invoke-AntiAI' ) - PrivateData = @{ + PrivateData = @{ PSData = @{ - Tags = @('Windows11', 'AI', 'Privacy', 'Security', 'Recall', 'Copilot', 'AntiAI') - ProjectUri = 'https://github.com/yourusername/NoIDPrivacy' + Tags = @('Windows11', 'AI', 'Privacy', 'Security', 'Recall', 'Copilot', 'AntiAI') + ProjectUri = 'https://github.com/yourusername/NoIDPrivacy' ReleaseNotes = @' v1.0.0 - Initial Release - Disables 8+ Windows 11 AI features using official Microsoft policies diff --git a/Modules/AntiAI/AntiAI.psm1 b/Modules/AntiAI/AntiAI.psm1 index 7a7de05..274d6c3 100644 --- a/Modules/AntiAI/AntiAI.psm1 +++ b/Modules/AntiAI/AntiAI.psm1 @@ -11,7 +11,7 @@ .NOTES Module: AntiAI - Version: 2.2.2 + Version: 2.2.3 Author: NoID Privacy #> @@ -27,7 +27,7 @@ $privateFunctions = @( 'Disable-Recall' 'Set-RecallProtection' 'Disable-Copilot' - 'Disable-CopilotAdvanced' # NEW v2.2.2: URI handlers, Edge sidebar, Recall export + 'Disable-CopilotAdvanced' # NEW v2.2.3: URI handlers, Edge sidebar, Recall export 'Disable-ClickToDo' 'Disable-SettingsAgent' 'Disable-ExplorerAI' # NEW: File Explorer AI Actions menu diff --git a/Modules/AntiAI/Public/Invoke-AntiAI.ps1 b/Modules/AntiAI/Public/Invoke-AntiAI.ps1 index 67fd3e0..43bbf61 100644 --- a/Modules/AntiAI/Public/Invoke-AntiAI.ps1 +++ b/Modules/AntiAI/Public/Invoke-AntiAI.ps1 @@ -52,7 +52,7 @@ .NOTES Author: NoID Privacy - Version: 2.2.2 + Version: 2.2.3 Requires: Windows 11 24H2 or later, Administrator privileges Impact: All AI features completely disabled, reboot required #> @@ -70,7 +70,7 @@ function Invoke-AntiAI { Write-Host "" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan - Write-Host " ANTI-AI MODULE v2.2.2" -ForegroundColor Cyan + Write-Host " ANTI-AI MODULE v2.2.3" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" Write-Host "Disables 15 AI features (32 policies):" -ForegroundColor White @@ -171,7 +171,7 @@ function Invoke-AntiAI { @{ Path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\Paint"; Name = "DisableImageCreator"; Type = "DWord" }, @{ Path = "HKLM:\SOFTWARE\Policies\WindowsNotepad"; Name = "DisableAIFeatures"; Type = "DWord" }, @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI"; Name = "DisableSettingsAgent"; Type = "DWord" }, - # NEW v2.2.2: Advanced Copilot Blocking + # NEW v2.2.3: Advanced Copilot Blocking @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI"; Name = "AllowRecallExport"; Type = "DWord" }, @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Edge"; Name = "EdgeSidebarEnabled"; Type = "DWord" }, @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Edge"; Name = "ShowHubsSidebar"; Type = "DWord" }, @@ -196,7 +196,7 @@ function Invoke-AntiAI { $prop = Get-ItemProperty -Path $t.Path -Name $t.Name -ErrorAction SilentlyContinue if ($null -ne $prop -and $prop.PSObject.Properties.Name -contains $t.Name) { $entry.Exists = $true - $entry.Value = $prop.$($t.Name) + $entry.Value = $prop.$($t.Name) } } } @@ -272,7 +272,8 @@ function Invoke-AntiAI { Register-Backup -Type "AntiAI" -Data $expJson -Name "Explorer_Advanced_Device_JSON" | Out-Null } } - } catch { + } + catch { Write-Host " WARNING: Failed to create JSON backup for Explorer Advanced: $_" -ForegroundColor Yellow } } @@ -355,7 +356,7 @@ function Invoke-AntiAI { } # ============================================================================ - # ADVANCED COPILOT BLOCKING (NEW v2.2.2) + # ADVANCED COPILOT BLOCKING (NEW v2.2.3) # ============================================================================ Write-Host "" Write-Host " [Advanced Copilot Blocks]" -ForegroundColor Cyan diff --git a/Modules/DNS/DNS.psd1 b/Modules/DNS/DNS.psd1 index f1ce468..347dddb 100644 --- a/Modules/DNS/DNS.psd1 +++ b/Modules/DNS/DNS.psd1 @@ -2,7 +2,7 @@ # Module manifest for DNS module RootModule = 'DNS.psm1' - ModuleVersion = '2.2.2' + ModuleVersion = '2.2.3' GUID = 'a8f7b3c9-4e5d-4a2b-9c1d-8f3e5a7b9c2d' Author = 'NexusOne23' CompanyName = 'Open Source Project' diff --git a/Modules/DNS/DNS.psm1 b/Modules/DNS/DNS.psm1 index 2a976ed..47cf81f 100644 --- a/Modules/DNS/DNS.psm1 +++ b/Modules/DNS/DNS.psm1 @@ -12,7 +12,7 @@ .NOTES Author: NoID Privacy - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges #> diff --git a/Modules/EdgeHardening/EdgeHardening.psd1 b/Modules/EdgeHardening/EdgeHardening.psd1 index dfb6941..4f3a282 100644 --- a/Modules/EdgeHardening/EdgeHardening.psd1 +++ b/Modules/EdgeHardening/EdgeHardening.psd1 @@ -1,30 +1,30 @@ @{ # Script module or binary module file associated with this manifest - RootModule = 'EdgeHardening.psm1' + RootModule = 'EdgeHardening.psm1' # Version number of this module - ModuleVersion = '2.2.2' + ModuleVersion = '2.2.3' # ID used to uniquely identify this module - GUID = '8e3f4c2a-9b1d-4e7a-a2c5-6f8b3d9e1a4c' + GUID = '8e3f4c2a-9b1d-4e7a-a2c5-6f8b3d9e1a4c' # Author of this module - Author = 'NexusOne23' + Author = 'NexusOne23' # Company or vendor of this module - CompanyName = 'Open Source Project' + CompanyName = 'Open Source Project' # Copyright statement for this module - Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' + Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' # Description of the functionality provided by this module - Description = 'Microsoft Edge Security Hardening based on MS Edge v139 Security Baseline. Applies 24 security policies to harden Microsoft Edge browser using native PowerShell (no LGPO.exe dependency). Includes SmartScreen enforcement, site isolation, SSL/TLS hardening, extension blocking, and IE mode restrictions.' + Description = 'Microsoft Edge Security Hardening based on MS Edge v139 Security Baseline. Applies 24 security policies to harden Microsoft Edge browser using native PowerShell (no LGPO.exe dependency). Includes SmartScreen enforcement, site isolation, SSL/TLS hardening, extension blocking, and IE mode restrictions.' # Minimum version of the PowerShell engine required by this module PowerShellVersion = '5.1' # Modules that must be imported into the global environment prior to importing this module - RequiredModules = @() + RequiredModules = @() # Functions to export from this module FunctionsToExport = @( @@ -33,22 +33,22 @@ ) # Cmdlets to export from this module - CmdletsToExport = @() + CmdletsToExport = @() # Variables to export from this module VariablesToExport = @() # Aliases to export from this module - AliasesToExport = @() + AliasesToExport = @() # Private data to pass to the module specified in RootModule/ModuleToProcess - PrivateData = @{ + PrivateData = @{ PSData = @{ - Tags = @('Security', 'Edge', 'Browser', 'Hardening', 'Baseline', 'Windows11', 'Privacy') - LicenseUri = '' - ProjectUri = '' + Tags = @('Security', 'Edge', 'Browser', 'Hardening', 'Baseline', 'Windows11', 'Privacy') + LicenseUri = '' + ProjectUri = '' ReleaseNotes = @" -v2.2.2 - Production Release +v2.2.3 - Production Release - Microsoft Edge v139 Security Baseline implementation - 20 security policies (native PowerShell, no LGPO.exe) - SmartScreen enforcement with override prevention diff --git a/Modules/EdgeHardening/EdgeHardening.psm1 b/Modules/EdgeHardening/EdgeHardening.psm1 index b732a67..1346092 100644 --- a/Modules/EdgeHardening/EdgeHardening.psm1 +++ b/Modules/EdgeHardening/EdgeHardening.psm1 @@ -16,7 +16,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges #> diff --git a/Modules/EdgeHardening/Public/Invoke-EdgeHardening.ps1 b/Modules/EdgeHardening/Public/Invoke-EdgeHardening.ps1 index 1ae15af..58b8ea2 100644 --- a/Modules/EdgeHardening/Public/Invoke-EdgeHardening.ps1 +++ b/Modules/EdgeHardening/Public/Invoke-EdgeHardening.ps1 @@ -48,7 +48,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges IMPORTANT: This applies Microsoft's recommended security baseline. diff --git a/Modules/EdgeHardening/Public/Test-EdgeHardening.ps1 b/Modules/EdgeHardening/Public/Test-EdgeHardening.ps1 index b0a698d..b6f55e0 100644 --- a/Modules/EdgeHardening/Public/Test-EdgeHardening.ps1 +++ b/Modules/EdgeHardening/Public/Test-EdgeHardening.ps1 @@ -23,7 +23,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Can be run without Administrator privileges #> @@ -103,8 +103,8 @@ function Test-EdgeHardening { return [PSCustomObject]@{ Compliant = $false - Message = "Test failed: $($_.Exception.Message)" - Details = @() + Message = "Test failed: $($_.Exception.Message)" + Details = @() } } } diff --git a/Modules/Privacy/Privacy.psd1 b/Modules/Privacy/Privacy.psd1 index 4198a66..7aabd85 100644 --- a/Modules/Privacy/Privacy.psd1 +++ b/Modules/Privacy/Privacy.psd1 @@ -1,11 +1,11 @@ @{ - RootModule = 'Privacy.psm1' - ModuleVersion = '2.2.2' - GUID = 'a9f7c8d3-2e5b-4a1f-9c3d-7e8f5a6b2c4d' - Author = 'NexusOne23' - CompanyName = 'Open Source Project' - Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' - Description = 'Privacy & Telemetry hardening module with Bloatware removal and OneDrive configuration. Supports 3 modes: MSRecommended (default), Strict (maximum privacy, apps still work), and Paranoid (hardcore).' + RootModule = 'Privacy.psm1' + ModuleVersion = '2.2.3' + GUID = 'a9f7c8d3-2e5b-4a1f-9c3d-7e8f5a6b2c4d' + Author = 'NexusOne23' + CompanyName = 'Open Source Project' + Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' + Description = 'Privacy & Telemetry hardening module with Bloatware removal and OneDrive configuration. Supports 3 modes: MSRecommended (default), Strict (maximum privacy, apps still work), and Paranoid (hardcore).' PowerShellVersion = '5.1' @@ -15,15 +15,15 @@ 'Test-PrivacyCompliance' ) - CmdletsToExport = @() + CmdletsToExport = @() VariablesToExport = @() - AliasesToExport = @() + AliasesToExport = @() - PrivateData = @{ + PrivateData = @{ PSData = @{ - Tags = @('Privacy', 'Telemetry', 'Bloatware', 'OneDrive', 'Windows11', 'Security') - LicenseUri = 'https://github.com/yourusername/NoIDPrivacyPro/blob/main/LICENSE' - ProjectUri = 'https://github.com/yourusername/NoIDPrivacyPro' + Tags = @('Privacy', 'Telemetry', 'Bloatware', 'OneDrive', 'Windows11', 'Security') + LicenseUri = 'https://github.com/yourusername/NoIDPrivacyPro/blob/main/LICENSE' + ProjectUri = 'https://github.com/yourusername/NoIDPrivacyPro' ReleaseNotes = 'Initial release - Privacy module with 3-mode support' } } diff --git a/Modules/Privacy/Privacy.psm1 b/Modules/Privacy/Privacy.psm1 index 8021252..6e96d95 100644 --- a/Modules/Privacy/Privacy.psm1 +++ b/Modules/Privacy/Privacy.psm1 @@ -16,7 +16,7 @@ .NOTES Module: Privacy - Version: 2.2.2 + Version: 2.2.3 Author: NoID Privacy #> diff --git a/Modules/SecurityBaseline/Public/Invoke-SecurityBaseline.ps1 b/Modules/SecurityBaseline/Public/Invoke-SecurityBaseline.ps1 index b5ba2c3..cb0e6a3 100644 --- a/Modules/SecurityBaseline/Public/Invoke-SecurityBaseline.ps1 +++ b/Modules/SecurityBaseline/Public/Invoke-SecurityBaseline.ps1 @@ -44,7 +44,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 - Self-Contained Edition + Version: 2.2.3 - Self-Contained Edition Requires: PowerShell 5.1+, Administrator privileges BREAKING CHANGE from v1.0: diff --git a/Modules/SecurityBaseline/SecurityBaseline.psd1 b/Modules/SecurityBaseline/SecurityBaseline.psd1 index 3392997..cf6b04e 100644 --- a/Modules/SecurityBaseline/SecurityBaseline.psd1 +++ b/Modules/SecurityBaseline/SecurityBaseline.psd1 @@ -1,32 +1,32 @@ @{ - RootModule = 'SecurityBaseline.psm1' - ModuleVersion = '2.2.2' - GUID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890' - Author = 'NexusOne23' - CompanyName = 'Open Source Project' - Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' - Description = 'Microsoft Security Baseline for Windows 11 25H2 - 425 hardening settings implementing enterprise-grade security standards. Self-contained, no LGPO.exe required. (437 entries parsed, 12 are INF metadata)' + RootModule = 'SecurityBaseline.psm1' + ModuleVersion = '2.2.3' + GUID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890' + Author = 'NexusOne23' + CompanyName = 'Open Source Project' + Copyright = '(c) 2025 NexusOne23. Licensed under GPL-3.0.' + Description = 'Microsoft Security Baseline for Windows 11 25H2 - 425 hardening settings implementing enterprise-grade security standards. Self-contained, no LGPO.exe required. (437 entries parsed, 12 are INF metadata)' PowerShellVersion = '5.1' - RequiredModules = @() + RequiredModules = @() FunctionsToExport = @( 'Invoke-SecurityBaseline', 'Restore-SecurityBaseline' ) - CmdletsToExport = @() + CmdletsToExport = @() VariablesToExport = @() - AliasesToExport = @() + AliasesToExport = @() - PrivateData = @{ + PrivateData = @{ PSData = @{ - Tags = @('Security', 'Hardening', 'Windows11', 'Baseline', 'Microsoft', 'Enterprise') - LicenseUri = '' - ProjectUri = '' + Tags = @('Security', 'Hardening', 'Windows11', 'Baseline', 'Microsoft', 'Enterprise') + LicenseUri = '' + ProjectUri = '' ReleaseNotes = @" -v2.2.2 - Self-Contained Edition +v2.2.3 - Self-Contained Edition - NO LGPO.exe REQUIRED! Fully self-contained implementation - 425 Microsoft Security Baseline settings for Windows 11 25H2 - 335 Registry policies (Computer + User) diff --git a/Modules/SecurityBaseline/SecurityBaseline.psm1 b/Modules/SecurityBaseline/SecurityBaseline.psm1 index a8579fc..74ee338 100644 --- a/Modules/SecurityBaseline/SecurityBaseline.psm1 +++ b/Modules/SecurityBaseline/SecurityBaseline.psm1 @@ -13,7 +13,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges #> diff --git a/NoIDPrivacy-Interactive.ps1 b/NoIDPrivacy-Interactive.ps1 index 2bd396f..fb30c6e 100644 --- a/NoIDPrivacy-Interactive.ps1 +++ b/NoIDPrivacy-Interactive.ps1 @@ -19,7 +19,7 @@ resulting from its use. USE AT YOUR OWN RISK. Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator For CLI mode use: NoIDPrivacy.ps1 -Module #> @@ -30,7 +30,7 @@ # No parameters - interactive mode only $ErrorActionPreference = 'Stop' -$Host.UI.RawUI.WindowTitle = "NoID Privacy v2.2.2" +$Host.UI.RawUI.WindowTitle = "NoID Privacy v2.2.3" # Set script root path (required by modules to load configs) $script:RootPath = $PSScriptRoot @@ -90,7 +90,7 @@ function Write-Banner { Clear-Host Write-Host "" Write-Host " ========================================" -ForegroundColor Cyan - Write-Host " NoID Privacy v2.2.2 " -ForegroundColor Cyan + Write-Host " NoID Privacy v2.2.3 " -ForegroundColor Cyan Write-Host " ========================================" -ForegroundColor Cyan Write-Host "" Write-Host " Professional Windows 11 Security & Privacy Hardening Framework" -ForegroundColor Gray @@ -105,7 +105,7 @@ function Write-Banner { $osBuild = if ($os) { $os.BuildNumber } else { $null } $psVersion = $PSVersionTable.PSVersion.ToString() - $envLine = " Version 2.2.2" + $envLine = " Version 2.2.3" if ($osBuild) { $envLine += " | Windows Build $osBuild" } diff --git a/NoIDPrivacy.ps1 b/NoIDPrivacy.ps1 index e32b83e..a114a19 100644 --- a/NoIDPrivacy.ps1 +++ b/NoIDPrivacy.ps1 @@ -50,7 +50,7 @@ resulting from its use. USE AT YOUR OWN RISK. Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Administrator privileges, Windows 11 License: GPL-3.0 (Core CLI). See LICENSE for full terms. @@ -111,13 +111,13 @@ $global:CurrentModule = "" # ============================================================================ # EXIT CODES - For CI/CD and automation integration # ============================================================================ -$script:EXIT_SUCCESS = 0 # All operations completed successfully -$script:EXIT_ERROR_GENERAL = 1 # General/unspecified error +$script:EXIT_SUCCESS = 0 # All operations completed successfully +$script:EXIT_ERROR_GENERAL = 1 # General/unspecified error $script:EXIT_ERROR_PREREQUISITES = 2 # System requirements not met -$script:EXIT_ERROR_CONFIG = 3 # Configuration file error -$script:EXIT_ERROR_MODULE = 4 # One or more modules failed -$script:EXIT_ERROR_FATAL = 5 # Fatal/unexpected exception -$script:EXIT_SUCCESS_REBOOT = 10 # Success, reboot required +$script:EXIT_ERROR_CONFIG = 3 # Configuration file error +$script:EXIT_ERROR_MODULE = 4 # One or more modules failed +$script:EXIT_ERROR_FATAL = 5 # Fatal/unexpected exception +$script:EXIT_SUCCESS_REBOOT = 10 # Success, reboot required # Script root path $script:RootPath = $PSScriptRoot @@ -135,7 +135,7 @@ try { $logDirectory = Join-Path $script:RootPath "Logs" Initialize-Logger -LogDirectory $logDirectory -MinimumLevel $logLevel - Write-Log -Level INFO -Message "=== NoID Privacy Framework v2.2.2 ===" -Module "Main" + Write-Log -Level INFO -Message "=== NoID Privacy Framework v2.2.3 ===" -Module "Main" Write-Log -Level INFO -Message "Starting framework initialization..." -Module "Main" # Load other Core modules @@ -216,7 +216,7 @@ catch { # Display banner Write-Host "" Write-Host "========================================" -ForegroundColor Cyan -Write-Host " NoID Privacy - v2.2.2" -ForegroundColor Cyan +Write-Host " NoID Privacy - v2.2.3" -ForegroundColor Cyan Write-Host " Windows 11 Security Hardening" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" @@ -255,23 +255,23 @@ if (-not $Module) { if ([string]::IsNullOrWhiteSpace($selection)) { $selection = "99" } $selection = $selection.ToUpper() - if ($selection -notin @('1','2','3','4','5','6','7','99','V','R','B','I','0')) { + if ($selection -notin @('1', '2', '3', '4', '5', '6', '7', '99', 'V', 'R', 'B', 'I', '0')) { Write-Host "" Write-Host "Invalid selection. Please choose from the menu." -ForegroundColor Red Write-Host "" } - } while ($selection -notin @('1','2','3','4','5','6','7','99','V','R','B','I','0')) + } while ($selection -notin @('1', '2', '3', '4', '5', '6', '7', '99', 'V', 'R', 'B', 'I', '0')) switch ($selection) { - "1" { $Module = "SecurityBaseline" } - "2" { $Module = "ASR" } - "3" { $Module = "DNS" } - "4" { $Module = "Privacy" } - "5" { $Module = "AntiAI" } - "6" { $Module = "EdgeHardening" } - "7" { $Module = "AdvancedSecurity" } + "1" { $Module = "SecurityBaseline" } + "2" { $Module = "ASR" } + "3" { $Module = "DNS" } + "4" { $Module = "Privacy" } + "5" { $Module = "AntiAI" } + "6" { $Module = "EdgeHardening" } + "7" { $Module = "AdvancedSecurity" } "99" { $Module = "All" } - "V" { + "V" { # Verify all settings Write-Host "" Write-Host "Running complete verification..." -ForegroundColor Cyan @@ -291,7 +291,7 @@ if (-not $Module) { $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") exit 0 } - "R" { + "R" { # Restore from backup - Interactive session selection from disk Write-Host "" Write-Host "========================================" -ForegroundColor Cyan @@ -365,7 +365,7 @@ if (-not $Module) { $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") exit 0 } - "B" { + "B" { # List backups Write-Host "" Write-Host "========================================" -ForegroundColor Cyan @@ -387,8 +387,8 @@ if (-not $Module) { foreach ($backup in $backups) { $age = (Get-Date) - $backup.CreationTime $ageStr = if ($age.TotalHours -lt 1) { "$([math]::Round($age.TotalMinutes)) minutes ago" } - elseif ($age.TotalDays -lt 1) { "$([math]::Round($age.TotalHours)) hours ago" } - else { "$([math]::Round($age.TotalDays)) days ago" } + elseif ($age.TotalDays -lt 1) { "$([math]::Round($age.TotalHours)) hours ago" } + else { "$([math]::Round($age.TotalDays)) days ago" } Write-Host " - $($backup.Name)" -ForegroundColor Green -NoNewline Write-Host " ($ageStr)" -ForegroundColor Gray @@ -404,7 +404,7 @@ if (-not $Module) { $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") exit 0 } - "I" { + "I" { # System information Write-Host "" Write-Host "========================================" -ForegroundColor Cyan @@ -451,7 +451,7 @@ if (-not $Module) { $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") exit 0 } - "0" { + "0" { Write-Host "Exiting..." -ForegroundColor Yellow exit 0 } diff --git a/README.md b/README.md index b65fbee..63a9fb5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![PowerShell](https://img.shields.io/badge/PowerShell-5.1%2B-blue.svg?logo=powershell)](https://github.com/PowerShell/PowerShell) [![Windows 11](https://img.shields.io/badge/Windows%2011-25H2-0078D4.svg?logo=windows11)](https://www.microsoft.com/windows/) [![License](https://img.shields.io/badge/license-GPL--3.0-green.svg?logo=gnu)](LICENSE) -[![Version](https://img.shields.io/badge/version-2.2.2-blue.svg)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-2.2.3-blue.svg)](CHANGELOG.md) [![Status](https://img.shields.io/badge/status-production--ready-brightgreen.svg)]() --- @@ -391,13 +391,13 @@ cd noid-privacy | Module | Settings | Description | Status | |--------|----------|-------------|--------| -| **SecurityBaseline** | 425 | Microsoft Security Baseline 25H2 | v2.2.2 | -| **ASR** | 19 | Attack Surface Reduction Rules | v2.2.2 | -| **DNS** | 5 | Secure DNS with DoH encryption | v2.2.2 | -| **Privacy** | 78 | Telemetry, Bloatware, OneDrive hardening (Strict) | v2.2.2 | -| **AntiAI** | 32 | AI lockdown (15 features, 32 compliance checks) | v2.2.2 | -| **EdgeHardening** | 24 | Microsoft Edge security (24 policies) | v2.2.2 | -| **AdvancedSecurity** | 50 | Beyond MS Baseline (SRP, Legacy protocols, Wireless Display, Discovery Protocols, IPv6) | v2.2.2 | +| **SecurityBaseline** | 425 | Microsoft Security Baseline 25H2 | v2.2.3 | +| **ASR** | 19 | Attack Surface Reduction Rules | v2.2.3 | +| **DNS** | 5 | Secure DNS with DoH encryption | v2.2.3 | +| **Privacy** | 78 | Telemetry, Bloatware, OneDrive hardening (Strict) | v2.2.3 | +| **AntiAI** | 32 | AI lockdown (15 features, 32 compliance checks) | v2.2.3 | +| **EdgeHardening** | 24 | Microsoft Edge security (24 policies) | v2.2.3 | +| **AdvancedSecurity** | 50 | Beyond MS Baseline (SRP, Legacy protocols, Wireless Display, Discovery Protocols, IPv6) | v2.2.3 | | **TOTAL** | **633** | **Complete Framework (Paranoid mode)** | **Production** | **Release Highlights:** @@ -852,10 +852,15 @@ The authors are not responsible for any damage or data loss. ## 📈 Project Status -**Current Version:** 2.2.2 -**Last Updated:** December 22, 2025 +**Current Version:** 2.2.3 +**Last Updated:** January 7, 2026 **Status:** Production-Ready +### Release Highlights v2.2.3 + +- **Critical Fix:** Restore Mode manual module selection crash +- Fix: `.Split()` wrong .NET overload → `-split` operator + ### Release Highlights v2.2.2 - **Performance:** Firewall snapshot 60-120s → 2-5s (batch query fix) @@ -867,15 +872,6 @@ The authors are not responsible for any damage or data loss. - **Fix:** `.Count` property bug in 5 files (Where-Object single-object results) - **Improved:** ASR prompt text ("untrusted" → "new software" - more neutral) -### Release Highlights v2.2.0 - -- 630+ settings (expanded from 580+) -- NonInteractive mode for GUI integration -- Third-party AV detection and graceful ASR skip -- AntiAI enhanced to 32 policies (was 24) -- Pre-Framework ASR snapshot -- Smart Registry Backup with JSON fallback - 📋 [See Full Changelog](CHANGELOG.md) --- diff --git a/Start-NoIDPrivacy.bat b/Start-NoIDPrivacy.bat index 54309b6..4411509 100644 --- a/Start-NoIDPrivacy.bat +++ b/Start-NoIDPrivacy.bat @@ -7,12 +7,12 @@ REM This script launches NoIDPrivacy-Interactive.ps1 with REM Administrator privileges (auto-elevation). REM REM Author: NexusOne23 -REM Version: 2.2.2 +REM Version: 2.2.3 REM ======================================== setlocal -title NoID Privacy v2.2.2 +title NoID Privacy v2.2.3 REM Get the directory where this batch file is located set "SCRIPT_DIR=%~dp0" diff --git a/Tests/Run-Tests.ps1 b/Tests/Run-Tests.ps1 index c519315..1202887 100644 --- a/Tests/Run-Tests.ps1 +++ b/Tests/Run-Tests.ps1 @@ -17,7 +17,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+, Pester 5.0+ .EXAMPLE diff --git a/Tests/Setup-TestEnvironment.ps1 b/Tests/Setup-TestEnvironment.ps1 index d1205a0..92c958b 100644 --- a/Tests/Setup-TestEnvironment.ps1 +++ b/Tests/Setup-TestEnvironment.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ .EXAMPLE diff --git a/Tests/Unit/ASR.Tests.ps1 b/Tests/Unit/ASR.Tests.ps1 index 18f38a2..f612724 100644 --- a/Tests/Unit/ASR.Tests.ps1 +++ b/Tests/Unit/ASR.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/AdvancedSecurity.Tests.ps1 b/Tests/Unit/AdvancedSecurity.Tests.ps1 index aa1111c..f238956 100644 --- a/Tests/Unit/AdvancedSecurity.Tests.ps1 +++ b/Tests/Unit/AdvancedSecurity.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/AntiAI.Tests.ps1 b/Tests/Unit/AntiAI.Tests.ps1 index 7903243..99243f9 100644 --- a/Tests/Unit/AntiAI.Tests.ps1 +++ b/Tests/Unit/AntiAI.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/DNS.Tests.ps1 b/Tests/Unit/DNS.Tests.ps1 index 35e959d..3e762e7 100644 --- a/Tests/Unit/DNS.Tests.ps1 +++ b/Tests/Unit/DNS.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/EdgeHardening.Tests.ps1 b/Tests/Unit/EdgeHardening.Tests.ps1 index e81dc85..20b3afd 100644 --- a/Tests/Unit/EdgeHardening.Tests.ps1 +++ b/Tests/Unit/EdgeHardening.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/ModuleTemplate.Tests.ps1 b/Tests/Unit/ModuleTemplate.Tests.ps1 index e420dbe..7bdf242 100644 --- a/Tests/Unit/ModuleTemplate.Tests.ps1 +++ b/Tests/Unit/ModuleTemplate.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tests/Unit/Privacy.Tests.ps1 b/Tests/Unit/Privacy.Tests.ps1 index d363d90..d29b352 100644 --- a/Tests/Unit/Privacy.Tests.ps1 +++ b/Tests/Unit/Privacy.Tests.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: Pester 5.0+ #> diff --git a/Tools/Generate-ReleaseChecksums.ps1 b/Tools/Generate-ReleaseChecksums.ps1 index 3ddc0a5..8c2dc24 100644 --- a/Tools/Generate-ReleaseChecksums.ps1 +++ b/Tools/Generate-ReleaseChecksums.ps1 @@ -13,10 +13,10 @@ Output file for checksums. Default: CHECKSUMS.sha256 in the same directory. .EXAMPLE - .\Generate-ReleaseChecksums.ps1 -ReleasePath "C:\Release\NoIDPrivacy-v2.2.2" + .\Generate-ReleaseChecksums.ps1 -ReleasePath "C:\Release\NoIDPrivacy-v2.2.3" .EXAMPLE - .\Generate-ReleaseChecksums.ps1 -ReleasePath ".\NoIDPrivacy-v2.2.2.zip" + .\Generate-ReleaseChecksums.ps1 -ReleasePath ".\NoIDPrivacy-v2.2.3.zip" #> [CmdletBinding()] @@ -36,10 +36,12 @@ Write-Host "`n=== NoID Privacy Release Checksum Generator ===" -ForegroundColor if (Test-Path $ReleasePath -PathType Container) { $files = Get-ChildItem -Path $ReleasePath -File -Recurse | Where-Object { $_.Extension -in '.zip', '.exe', '.ps1', '.psm1' } $basePath = $ReleasePath -} elseif (Test-Path $ReleasePath -PathType Leaf) { +} +elseif (Test-Path $ReleasePath -PathType Leaf) { $files = Get-Item $ReleasePath $basePath = Split-Path $ReleasePath -Parent -} else { +} +else { Write-Error "Path not found: $ReleasePath" exit 1 } diff --git a/Tools/Parse-EdgeBaseline.ps1 b/Tools/Parse-EdgeBaseline.ps1 index 2484765..c252314 100644 --- a/Tools/Parse-EdgeBaseline.ps1 +++ b/Tools/Parse-EdgeBaseline.ps1 @@ -18,7 +18,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ .EXAMPLE @@ -142,21 +142,26 @@ function Read-PolFile { # Parse based on type switch ($type) { - 1 { # REG_SZ (String) + 1 { + # REG_SZ (String) $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) } - 2 { # REG_EXPAND_SZ + 2 { + # REG_EXPAND_SZ $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) } - 3 { # REG_BINARY + 3 { + # REG_BINARY $data = $dataBytes } - 4 { # REG_DWORD + 4 { + # REG_DWORD if ($dataBytes.Length -ge 4) { $data = [BitConverter]::ToInt32($dataBytes, 0) } } - 7 { # REG_MULTI_SZ + 7 { + # REG_MULTI_SZ $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) -split '\x00' } default { @@ -172,9 +177,9 @@ function Read-PolFile { # Add entry $entries += [PSCustomObject]@{ - KeyName = $keyName + KeyName = $keyName ValueName = $valueName - Type = switch ($type) { + Type = switch ($type) { 1 { "REG_SZ" } 2 { "REG_EXPAND_SZ" } 3 { "REG_BINARY" } @@ -183,7 +188,7 @@ function Read-PolFile { 11 { "REG_QWORD" } default { "Unknown($type)" } } - Data = $data + Data = $data } } @@ -273,9 +278,9 @@ if ($allComputerPolicies.Count -gt 0) { # Create summary $summary = [PSCustomObject]@{ TotalEdgePolicies = $allComputerPolicies.Count - ParsedDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" - BaselineVersion = "Edge v139" - RegistryPaths = ($allComputerPolicies | Select-Object -ExpandProperty KeyName -Unique | Sort-Object) + ParsedDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + BaselineVersion = "Edge v139" + RegistryPaths = ($allComputerPolicies | Select-Object -ExpandProperty KeyName -Unique | Sort-Object) } $summaryFile = Join-Path $OutputPath "Summary.json" diff --git a/Tools/Parse-SecurityBaseline.ps1 b/Tools/Parse-SecurityBaseline.ps1 index 3d0f09c..2afc22b 100644 --- a/Tools/Parse-SecurityBaseline.ps1 +++ b/Tools/Parse-SecurityBaseline.ps1 @@ -25,7 +25,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ .EXAMPLE @@ -150,21 +150,26 @@ function Read-PolFile { # Parse based on type switch ($type) { - 1 { # REG_SZ (String) + 1 { + # REG_SZ (String) $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) } - 2 { # REG_EXPAND_SZ + 2 { + # REG_EXPAND_SZ $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) } - 3 { # REG_BINARY + 3 { + # REG_BINARY $data = $dataBytes } - 4 { # REG_DWORD + 4 { + # REG_DWORD if ($dataBytes.Length -ge 4) { $data = [BitConverter]::ToInt32($dataBytes, 0) } } - 7 { # REG_MULTI_SZ + 7 { + # REG_MULTI_SZ $data = [System.Text.Encoding]::Unicode.GetString($dataBytes).TrimEnd([char]0) -split '\x00' } default { @@ -180,9 +185,9 @@ function Read-PolFile { # Add entry $entries += [PSCustomObject]@{ - KeyName = $keyName + KeyName = $keyName ValueName = $valueName - Type = switch ($type) { + Type = switch ($type) { 1 { "REG_SZ" } 2 { "REG_EXPAND_SZ" } 3 { "REG_BINARY" } @@ -191,7 +196,7 @@ function Read-PolFile { 11 { "REG_QWORD" } default { "Unknown($type)" } } - Data = $data + Data = $data } } @@ -296,10 +301,10 @@ function Read-AuditCsv { # Skip header row $policies = $csv | Select-Object -Skip 1 | ForEach-Object { [PSCustomObject]@{ - Subcategory = $_.'Subcategory' - SubcategoryGUID = $_.'Subcategory GUID' + Subcategory = $_.'Subcategory' + SubcategoryGUID = $_.'Subcategory GUID' InclusionSetting = $_.'Inclusion Setting' - SettingValue = $_.'Setting Value' + SettingValue = $_.'Setting Value' } } @@ -346,17 +351,17 @@ $gpoMapping = @{ $gpoPath = Join-Path $BaselinePath "GPOs" $allSettings = @{ - RegistryPolicies = @{ + RegistryPolicies = @{ Computer = @() - User = @() + User = @() } SecurityTemplates = @{} - AuditPolicies = @() - Summary = @{ + AuditPolicies = @() + Summary = @{ TotalRegistrySettings = 0 TotalSecuritySettings = 0 - TotalAuditPolicies = 0 - TotalSettings = 0 + TotalAuditPolicies = 0 + TotalSettings = 0 } } @@ -381,11 +386,11 @@ foreach ($guid in $gpoMapping.Keys) { foreach ($entry in $entries) { $allSettings.RegistryPolicies.Computer += [PSCustomObject]@{ - GPO = $gpoName - KeyName = $entry.KeyName + GPO = $gpoName + KeyName = $entry.KeyName ValueName = $entry.ValueName - Type = $entry.Type - Data = $entry.Data + Type = $entry.Type + Data = $entry.Data } } @@ -401,11 +406,11 @@ foreach ($guid in $gpoMapping.Keys) { foreach ($entry in $entries) { $allSettings.RegistryPolicies.User += [PSCustomObject]@{ - GPO = $gpoName - KeyName = $entry.KeyName + GPO = $gpoName + KeyName = $entry.KeyName ValueName = $entry.ValueName - Type = $entry.Type - Data = $entry.Data + Type = $entry.Type + Data = $entry.Data } } @@ -435,11 +440,11 @@ foreach ($guid in $gpoMapping.Keys) { foreach ($policy in $policies) { $allSettings.AuditPolicies += [PSCustomObject]@{ - GPO = $gpoName - Subcategory = $policy.Subcategory - SubcategoryGUID = $policy.SubcategoryGUID + GPO = $gpoName + Subcategory = $policy.Subcategory + SubcategoryGUID = $policy.SubcategoryGUID InclusionSetting = $policy.InclusionSetting - SettingValue = $policy.SettingValue + SettingValue = $policy.SettingValue } } @@ -452,8 +457,8 @@ foreach ($guid in $gpoMapping.Keys) { # Calculate total $allSettings.Summary.TotalSettings = $allSettings.Summary.TotalRegistrySettings + - $allSettings.Summary.TotalSecuritySettings + - $allSettings.Summary.TotalAuditPolicies +$allSettings.Summary.TotalSecuritySettings + +$allSettings.Summary.TotalAuditPolicies # Save outputs Write-Host "Saving parsed settings..." -ForegroundColor Cyan diff --git a/Tools/Verify-Complete-Hardening.ps1 b/Tools/Verify-Complete-Hardening.ps1 index 6aadf2a..533bebf 100644 --- a/Tools/Verify-Complete-Hardening.ps1 +++ b/Tools/Verify-Complete-Hardening.ps1 @@ -27,7 +27,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 #> #Requires -Version 5.1 @@ -130,10 +130,10 @@ function Get-RegistryChecksFromJson { # Skip metadata and excluded categories # NOTE: EnterpriseProtection is NOT skipped - it contains valid registry paths! if ($propName -in @('Mode', 'Description', 'BestFor', 'Warnings', 'Services', 'ScheduledTasks', - 'Summary', 'AutomaticallyBlockedByMasterSwitch', 'ModuleName', 'Version', - 'TotalFeatures', 'TotalPolicies', 'URIHandlers', 'Note', 'FilePath', - 'HostsEntries', 'CloudBased', 'RequiresReboot', - 'RequiresADMX', 'Impact', 'Name')) { + 'Summary', 'AutomaticallyBlockedByMasterSwitch', 'ModuleName', 'Version', + 'TotalFeatures', 'TotalPolicies', 'URIHandlers', 'Note', 'FilePath', + 'HostsEntries', 'CloudBased', 'RequiresReboot', + 'RequiresADMX', 'Impact', 'Name')) { continue } @@ -962,78 +962,16 @@ try { $currentASRIds = $mpPreference.AttackSurfaceReductionRules_Ids $currentASRActions = $mpPreference.AttackSurfaceReductionRules_Actions - # Load expected ASR rules - JSON is array directly - $asrRules = Get-Content (Join-Path $asrConfigPath "ASR-Rules.json") -Raw | ConvertFrom-Json + # Load expected ASR rules - JSON is array directly + $asrRules = Get-Content (Join-Path $asrConfigPath "ASR-Rules.json") -Raw | ConvertFrom-Json - $asrFailed = @() - $asrPassed = @() + $asrFailed = @() + $asrPassed = @() - # Check if ASR rules are configured at all - if ($null -eq $currentASRIds -or $currentASRIds.Count -eq 0) { - # No ASR rules configured - mark all as failed - foreach ($rule in $asrRules) { - $results.Failed++ - $expectedActionText = if ($rule.Action -eq 1) { "Block" } elseif ($rule.Action -eq 2) { "Audit" } else { "Disabled" } - $asrFailed += [PSCustomObject]@{ - Rule = $rule.Name - GUID = $rule.GUID - Expected = $expectedActionText - Actual = "Not configured" - } - } - } - else { - # Rules where both BLOCK (1) and AUDIT (2) are considered "Pass" - # These are user-configurable rules where either mode is valid - $flexibleRules = @( - "d1e49aac-8f56-4280-b9ba-993a6d77406c", # PSExec/WMI (Management Tools) - "01443614-cd74-433a-b99e-2ecdc07bfc25" # Prevalence (New/Unknown Software) - ) - - foreach ($rule in $asrRules) { - # Case-insensitive GUID matching (Get-MpPreference may return different case) - $index = -1 - for ($i = 0; $i -lt $currentASRIds.Count; $i++) { - if ($currentASRIds[$i] -eq $rule.GUID) { - $index = $i - break - } - } - - if ($index -ge 0) { - $actualAction = $currentASRActions[$index] - $expectedAction = $rule.Action - - # Check if this is a flexible rule (Block or Audit both count as Pass) - $isFlexibleRule = $flexibleRules -contains $rule.GUID - $isActiveMode = $actualAction -in @(1, 2) # Block or Audit - - # For flexible rules: Pass if Block OR Audit - # For other rules: Pass only if exact match - $rulePassed = if ($isFlexibleRule) { $isActiveMode } else { $actualAction -eq $expectedAction } - - if ($rulePassed) { - $results.Verified++ - $actionText = if ($actualAction -eq 1) { "Block" } elseif ($actualAction -eq 2) { "Audit" } else { "Disabled" } - $asrPassed += [PSCustomObject]@{ - Rule = $rule.Name - Expected = $actionText - Actual = $actionText - } - } - else { - $results.Failed++ - $expectedActionText = if ($expectedAction -eq 1) { "Block" } elseif ($expectedAction -eq 2) { "Audit" } else { "Disabled" } - $actualActionText = if ($actualAction -eq 1) { "Block" } elseif ($actualAction -eq 2) { "Audit" } else { "Disabled" } - $asrFailed += [PSCustomObject]@{ - Rule = $rule.Name - GUID = $rule.GUID - Expected = $expectedActionText - Actual = $actualActionText - } - } - } - else { + # Check if ASR rules are configured at all + if ($null -eq $currentASRIds -or $currentASRIds.Count -eq 0) { + # No ASR rules configured - mark all as failed + foreach ($rule in $asrRules) { $results.Failed++ $expectedActionText = if ($rule.Action -eq 1) { "Block" } elseif ($rule.Action -eq 2) { "Audit" } else { "Disabled" } $asrFailed += [PSCustomObject]@{ @@ -1044,28 +982,90 @@ try { } } } - } - - # Add to AllSettings for HTML report - $asrPassedCount = $results.ASRRules - $asrFailed.Count - $results.AllSettings += [PSCustomObject]@{ - Category = "ASR" - Total = $results.ASRRules - Passed = $asrPassedCount - Failed = $asrFailed.Count - PassedDetails = $asrPassed - FailedDetails = $asrFailed - } - - if ($asrFailed.Count -gt 0) { - $results.FailedSettings += [PSCustomObject]@{ - Category = "ASR" - Count = $asrFailed.Count - Details = $asrFailed + else { + # Rules where both BLOCK (1) and AUDIT (2) are considered "Pass" + # These are user-configurable rules where either mode is valid + $flexibleRules = @( + "d1e49aac-8f56-4280-b9ba-993a6d77406c", # PSExec/WMI (Management Tools) + "01443614-cd74-433a-b99e-2ecdc07bfc25" # Prevalence (New/Unknown Software) + ) + + foreach ($rule in $asrRules) { + # Case-insensitive GUID matching (Get-MpPreference may return different case) + $index = -1 + for ($i = 0; $i -lt $currentASRIds.Count; $i++) { + if ($currentASRIds[$i] -eq $rule.GUID) { + $index = $i + break + } + } + + if ($index -ge 0) { + $actualAction = $currentASRActions[$index] + $expectedAction = $rule.Action + + # Check if this is a flexible rule (Block or Audit both count as Pass) + $isFlexibleRule = $flexibleRules -contains $rule.GUID + $isActiveMode = $actualAction -in @(1, 2) # Block or Audit + + # For flexible rules: Pass if Block OR Audit + # For other rules: Pass only if exact match + $rulePassed = if ($isFlexibleRule) { $isActiveMode } else { $actualAction -eq $expectedAction } + + if ($rulePassed) { + $results.Verified++ + $actionText = if ($actualAction -eq 1) { "Block" } elseif ($actualAction -eq 2) { "Audit" } else { "Disabled" } + $asrPassed += [PSCustomObject]@{ + Rule = $rule.Name + Expected = $actionText + Actual = $actionText + } + } + else { + $results.Failed++ + $expectedActionText = if ($expectedAction -eq 1) { "Block" } elseif ($expectedAction -eq 2) { "Audit" } else { "Disabled" } + $actualActionText = if ($actualAction -eq 1) { "Block" } elseif ($actualAction -eq 2) { "Audit" } else { "Disabled" } + $asrFailed += [PSCustomObject]@{ + Rule = $rule.Name + GUID = $rule.GUID + Expected = $expectedActionText + Actual = $actualActionText + } + } + } + else { + $results.Failed++ + $expectedActionText = if ($rule.Action -eq 1) { "Block" } elseif ($rule.Action -eq 2) { "Audit" } else { "Disabled" } + $asrFailed += [PSCustomObject]@{ + Rule = $rule.Name + GUID = $rule.GUID + Expected = $expectedActionText + Actual = "Not configured" + } + } + } } - } - Write-Host " ASR Rules: $($results.ASRRules - $asrFailed.Count)/$($results.ASRRules) verified" -ForegroundColor $(if ($asrFailed.Count -eq 0) { "Green" } else { "Yellow" }) + # Add to AllSettings for HTML report + $asrPassedCount = $results.ASRRules - $asrFailed.Count + $results.AllSettings += [PSCustomObject]@{ + Category = "ASR" + Total = $results.ASRRules + Passed = $asrPassedCount + Failed = $asrFailed.Count + PassedDetails = $asrPassed + FailedDetails = $asrFailed + } + + if ($asrFailed.Count -gt 0) { + $results.FailedSettings += [PSCustomObject]@{ + Category = "ASR" + Count = $asrFailed.Count + Details = $asrFailed + } + } + + Write-Host " ASR Rules: $($results.ASRRules - $asrFailed.Count)/$($results.ASRRules) verified" -ForegroundColor $(if ($asrFailed.Count -eq 0) { "Green" } else { "Yellow" }) } # End of else (Defender active) } catch { @@ -1303,8 +1303,8 @@ try { if ($entry.ServerAddresses -and $entry.ServerAddresses.Count -gt 0) { # Check if it's not DHCP (empty or localhost fallback) $isDHCP = ($entry.ServerAddresses.Count -eq 0) -or - ($entry.ServerAddresses -contains '127.0.0.1') -or - ($entry.AddressOrigin -eq 'DHCP') + ($entry.ServerAddresses -contains '127.0.0.1') -or + ($entry.AddressOrigin -eq 'DHCP') if (-not $isDHCP) { $staticDNS = $true @@ -1796,10 +1796,10 @@ try { # We validate both Enabled=0 and DisabledByDefault=1 per version/component $tlsChecks = @( # Enabled flags - @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.0 Server Disabled"; Optional = $false } - @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.0 Client Disabled"; Optional = $false } - @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.1 Server Disabled"; Optional = $false } - @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.1 Client Disabled"; Optional = $false } + @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.0 Server Disabled"; Optional = $false } + @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.0 Client Disabled"; Optional = $false } + @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.1 Server Disabled"; Optional = $false } + @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client"; Name = "Enabled"; Expected = 0; Desc = "TLS 1.1 Client Disabled"; Optional = $false } # DisabledByDefault flags @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server"; Name = "DisabledByDefault"; Expected = 1; Desc = "TLS 1.0 Server DisabledByDefault"; Optional = $false } @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client"; Name = "DisabledByDefault"; Expected = 1; Desc = "TLS 1.0 Client DisabledByDefault"; Optional = $false } @@ -1812,24 +1812,24 @@ try { # Reference: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/disable-http-proxy-auth-features # NOTE: HKCU AutoDetect is set per-user via HKU in Apply, verified separately below $wpadChecks = @( - @{ Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp"; Name = "DisableWpad"; Expected = 1; Desc = "WPAD Disabled (Official MS Key)"; Optional = $false } - @{ Path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad"; Name = "WpadOverride"; Expected = 1; Desc = "WPAD Disabled (WpadOverride)"; Optional = $false } - @{ Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"; Name = "AutoDetect"; Expected = 0; Desc = "WPAD AutoDetect (HKLM)"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp"; Name = "DisableWpad"; Expected = 1; Desc = "WPAD Disabled (Official MS Key)"; Optional = $false } + @{ Path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad"; Name = "WpadOverride"; Expected = 1; Desc = "WPAD Disabled (WpadOverride)"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"; Name = "AutoDetect"; Expected = 0; Desc = "WPAD AutoDetect (HKLM)"; Optional = $false } ) # SRP Root Policy (2 checks) - ALWAYS required for CVE-2025-9491 mitigation $srpRootChecks = @( - @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers"; Name = "DefaultLevel"; Expected = 262144; Desc = "SRP DefaultLevel (Unrestricted)"; Optional = $false } - @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers"; Name = "TransparentEnabled"; Expected = 1; Desc = "SRP TransparentEnabled"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers"; Name = "DefaultLevel"; Expected = 262144; Desc = "SRP DefaultLevel (Unrestricted)"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers"; Name = "TransparentEnabled"; Expected = 1; Desc = "SRP TransparentEnabled"; Optional = $false } ) # Firewall Shields Up (1 check) - Maximum profile only, blocks ALL incoming on Public network # Optional = true because it's only applied for Maximum profile (user choice) $shieldsUpCheck = @{ - Path = "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\PublicProfile" - Name = "DoNotAllowExceptions" + Path = "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\PublicProfile" + Name = "DoNotAllowExceptions" Expected = 1 - Desc = "Firewall Shields Up (Maximum only)" + Desc = "Firewall Shields Up (Maximum only)" Optional = $true } @@ -1837,10 +1837,10 @@ try { # Optional = true because only applied for Maximum profile (user choice) # Check 1: mDNS disabled via registry $discoveryMdnsCheck = @{ - Path = "HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters" - Name = "EnableMDNS" + Path = "HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters" + Name = "EnableMDNS" Expected = 0 - Desc = "Discovery Protocols: mDNS Disabled (Maximum only)" + Desc = "Discovery Protocols: mDNS Disabled (Maximum only)" Optional = $true } @@ -1850,10 +1850,10 @@ try { # IPv6 Disable (mitm6 attack mitigation) - Maximum profile only # Optional = true because only applied for Maximum profile (user choice) $ipv6Check = @{ - Path = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" - Name = "DisabledComponents" + Path = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" + Name = "DisabledComponents" Expected = 255 # 0xFF = completely disabled - Desc = "IPv6 Disabled (mitm6 mitigation, Maximum only)" + Desc = "IPv6 Disabled (mitm6 mitigation, Maximum only)" Optional = $true } @@ -1888,10 +1888,10 @@ try { # Windows Update (4 Checks) - ALWAYS required - matches AdvancedSecurity module Config/WindowsUpdate.json $wuChecks = @( - @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "AllowOptionalContent"; Expected = 1; Desc = "WU: Get latest updates immediately (Policy)"; Optional = $false } - @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "SetAllowOptionalContent"; Expected = 1; Desc = "WU: AllowOptionalContent Policy Flag"; Optional = $false } - @{ Path = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings"; Name = "AllowMUUpdateService"; Expected = 1; Desc = "WU: Microsoft Update (Office, drivers)"; Optional = $false } - @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization"; Name = "DODownloadMode"; Expected = 0; Desc = "WU: P2P Delivery Optimization OFF"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "AllowOptionalContent"; Expected = 1; Desc = "WU: Get latest updates immediately (Policy)"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; Name = "SetAllowOptionalContent"; Expected = 1; Desc = "WU: AllowOptionalContent Policy Flag"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings"; Name = "AllowMUUpdateService"; Expected = 1; Desc = "WU: Microsoft Update (Office, drivers)"; Optional = $false } + @{ Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization"; Name = "DODownloadMode"; Expected = 0; Desc = "WU: P2P Delivery Optimization OFF"; Optional = $false } ) # Finger Protocol (1 check) - verify outbound firewall rule created by AdvancedSecurity @@ -1911,7 +1911,8 @@ try { else { $actualDesc = if ($portFilter) { "Protocol=$($portFilter.Protocol), RemotePort=$($portFilter.RemotePort)" - } else { + } + else { "No port filter" } } @@ -2050,8 +2051,8 @@ try { $hkuPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" $userSIDs = Get-ChildItem -Path "HKU:\" -ErrorAction SilentlyContinue | - Where-Object { $_.PSChildName -match '^S-1-5-21-' -and $_.PSChildName -notmatch '_Classes$' } | - Select-Object -ExpandProperty PSChildName + Where-Object { $_.PSChildName -match '^S-1-5-21-' -and $_.PSChildName -notmatch '_Classes$' } | + Select-Object -ExpandProperty PSChildName $hkuCompliant = $true $hkuActualValue = "All users compliant" @@ -2222,10 +2223,10 @@ try { $totalAdapters = $adapters.Count $disabledCount = 0 - $nonCompliant = @() + $nonCompliant = @() foreach ($adapter in $adapters) { - $adapterName = if ($adapter.Description.Length -gt 40) { $adapter.Description.Substring(0,37) + "..." } else { $adapter.Description } + $adapterName = if ($adapter.Description.Length -gt 40) { $adapter.Description.Substring(0, 37) + "..." } else { $adapter.Description } if ($adapter.TcpipNetbiosOptions -eq 2) { $disabledCount++ } @@ -2545,7 +2546,7 @@ catch { # drift from per-category counters in case some success paths didn't # manually increment $results.Verified. $results.TotalSettings = ($results.AllSettings | Measure-Object -Property Total -Sum).Sum -$results.Verified = ($results.AllSettings | Measure-Object -Property Passed -Sum).Sum +$results.Verified = ($results.AllSettings | Measure-Object -Property Passed -Sum).Sum $results.Duration = (Get-Date) - $startTime @@ -3244,7 +3245,7 @@ try {
-

NoID Privacy v2.2.2

+

NoID Privacy v2.2.3

Complete Hardening Compliance Report

All $totalSettings Settings Verified
@@ -3264,7 +3265,7 @@ try {
Framework Version - NoID Privacy v2.2.2 + NoID Privacy v2.2.3
@@ -3423,11 +3424,11 @@ try { $friendlyName = $zoneSettingNames[$settingName] if ($friendlyName) { $zoneName = if ($pathInfo -like "*Zones\\0*") { "My Computer" } - elseif ($pathInfo -like "*Zones\\1*") { "Local Intranet" } - elseif ($pathInfo -like "*Zones\\2*") { "Trusted Sites" } - elseif ($pathInfo -like "*Zones\\3*") { "Internet" } - elseif ($pathInfo -like "*Zones\\4*") { "Restricted Sites" } - else { "Zone" } + elseif ($pathInfo -like "*Zones\\1*") { "Local Intranet" } + elseif ($pathInfo -like "*Zones\\2*") { "Trusted Sites" } + elseif ($pathInfo -like "*Zones\\3*") { "Internet" } + elseif ($pathInfo -like "*Zones\\4*") { "Restricted Sites" } + else { "Zone" } $settingName = "[$zoneName] $friendlyName" } } @@ -3440,14 +3441,14 @@ try { elseif (($settingName -eq "iexplore.exe" -or $settingName -eq "explorer.exe") -and $pathInfo -like "*FeatureControl*") { # IE FeatureControl settings $featureNames = @{ - "FEATURE_DISABLE_MK_PROTOCOL" = "Disable MK Protocol (Security)" - "FEATURE_MIME_HANDLING" = "MIME Handling Security" - "FEATURE_MIME_SNIFFING" = "MIME Sniffing Protection" + "FEATURE_DISABLE_MK_PROTOCOL" = "Disable MK Protocol (Security)" + "FEATURE_MIME_HANDLING" = "MIME Handling Security" + "FEATURE_MIME_SNIFFING" = "MIME Sniffing Protection" "FEATURE_RESTRICT_ACTIVEXINSTALL" = "Restrict ActiveX Install" - "FEATURE_RESTRICT_FILEDOWNLOAD" = "Restrict File Download" - "FEATURE_SECURITYBAND" = "Security Band (Info Bar)" - "FEATURE_WINDOW_RESTRICTIONS" = "Window Restrictions (Pop-up Block)" - "FEATURE_ZONE_ELEVATION" = "Zone Elevation Block" + "FEATURE_RESTRICT_FILEDOWNLOAD" = "Restrict File Download" + "FEATURE_SECURITYBAND" = "Security Band (Info Bar)" + "FEATURE_WINDOW_RESTRICTIONS" = "Window Restrictions (Pop-up Block)" + "FEATURE_ZONE_ELEVATION" = "Zone Elevation Block" } $processName = if ($settingName -eq "iexplore.exe") { "IE" } else { "Explorer" } foreach ($feature in $featureNames.Keys) { @@ -3585,11 +3586,11 @@ try { $friendlyName = $zoneSettingNames[$settingName] if ($friendlyName) { $zoneName = if ($pathInfo -like "*Zones\\0*" -or $pathInfo -like "*Zones\0*") { "My Computer" } - elseif ($pathInfo -like "*Zones\\1*" -or $pathInfo -like "*Zones\1*") { "Local Intranet" } - elseif ($pathInfo -like "*Zones\\2*" -or $pathInfo -like "*Zones\2*") { "Trusted Sites" } - elseif ($pathInfo -like "*Zones\\3*" -or $pathInfo -like "*Zones\3*") { "Internet" } - elseif ($pathInfo -like "*Zones\\4*" -or $pathInfo -like "*Zones\4*") { "Restricted Sites" } - else { "Zone" } + elseif ($pathInfo -like "*Zones\\1*" -or $pathInfo -like "*Zones\1*") { "Local Intranet" } + elseif ($pathInfo -like "*Zones\\2*" -or $pathInfo -like "*Zones\2*") { "Trusted Sites" } + elseif ($pathInfo -like "*Zones\\3*" -or $pathInfo -like "*Zones\3*") { "Internet" } + elseif ($pathInfo -like "*Zones\\4*" -or $pathInfo -like "*Zones\4*") { "Restricted Sites" } + else { "Zone" } $settingName = "[$zoneName] $friendlyName" } } @@ -3602,14 +3603,14 @@ try { elseif (($settingName -eq "iexplore.exe" -or $settingName -eq "explorer.exe") -and $pathInfo -like "*FeatureControl*") { # IE FeatureControl settings $featureNames = @{ - "FEATURE_DISABLE_MK_PROTOCOL" = "Disable MK Protocol (Security)" - "FEATURE_MIME_HANDLING" = "MIME Handling Security" - "FEATURE_MIME_SNIFFING" = "MIME Sniffing Protection" + "FEATURE_DISABLE_MK_PROTOCOL" = "Disable MK Protocol (Security)" + "FEATURE_MIME_HANDLING" = "MIME Handling Security" + "FEATURE_MIME_SNIFFING" = "MIME Sniffing Protection" "FEATURE_RESTRICT_ACTIVEXINSTALL" = "Restrict ActiveX Install" - "FEATURE_RESTRICT_FILEDOWNLOAD" = "Restrict File Download" - "FEATURE_SECURITYBAND" = "Security Band (Info Bar)" - "FEATURE_WINDOW_RESTRICTIONS" = "Window Restrictions (Pop-up Block)" - "FEATURE_ZONE_ELEVATION" = "Zone Elevation Block" + "FEATURE_RESTRICT_FILEDOWNLOAD" = "Restrict File Download" + "FEATURE_SECURITYBAND" = "Security Band (Info Bar)" + "FEATURE_WINDOW_RESTRICTIONS" = "Window Restrictions (Pop-up Block)" + "FEATURE_ZONE_ELEVATION" = "Zone Elevation Block" } $processName = if ($settingName -eq "iexplore.exe") { "IE" } else { "Explorer" } foreach ($feature in $featureNames.Keys) { @@ -3706,7 +3707,7 @@ try { diff --git a/Utils/Compatibility.ps1 b/Utils/Compatibility.ps1 index a355b5b..82689de 100644 --- a/Utils/Compatibility.ps1 +++ b/Utils/Compatibility.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> diff --git a/Utils/Dependencies.ps1 b/Utils/Dependencies.ps1 index 9c79de2..fd1077e 100644 --- a/Utils/Dependencies.ps1 +++ b/Utils/Dependencies.ps1 @@ -7,7 +7,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -55,9 +55,9 @@ function Test-SecEditAvailable { $result = [PSCustomObject]@{ Available = $false - Path = $null - Version = $null - Error = $null + Path = $null + Version = $null + Error = $null } try { @@ -105,9 +105,9 @@ function Test-AuditPolAvailable { $result = [PSCustomObject]@{ Available = $false - Path = $null - Version = $null - Error = $null + Path = $null + Version = $null + Error = $null } try { @@ -154,10 +154,10 @@ function Test-WindowsDefenderAvailable { param() $result = [PSCustomObject]@{ - Available = $false + Available = $false ServiceRunning = $false - ServiceName = "WinDefend" - Error = $null + ServiceName = "WinDefend" + Error = $null } try { @@ -198,16 +198,16 @@ function Test-AllDependencies { param() $result = [PSCustomObject]@{ - AllAvailable = $true + AllAvailable = $true SecurityBaseline = @{ - secedit = $null + secedit = $null auditpol = $null } - ASR = @{ + ASR = @{ defender = $null } - MissingCritical = @() - MissingOptional = @() + MissingCritical = @() + MissingOptional = @() } # Check secedit.exe (CRITICAL for SecurityBaseline) diff --git a/Utils/Hardware.ps1 b/Utils/Hardware.ps1 index 4bae556..01f11c0 100644 --- a/Utils/Hardware.ps1 +++ b/Utils/Hardware.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -25,24 +25,24 @@ function Test-VBSCapable { param() $requirements = @{ - UEFI = Test-UEFIBoot - SecureBoot = Test-SecureBootEnabled - TPM = (Test-TPMAvailable).Present + UEFI = Test-UEFIBoot + SecureBoot = Test-SecureBootEnabled + TPM = (Test-TPMAvailable).Present Virtualization = Test-VirtualizationEnabled - Windows11 = (Get-WindowsVersion).IsWindows11 + Windows11 = (Get-WindowsVersion).IsWindows11 } $allMet = $requirements.UEFI -and $requirements.SecureBoot -and ` - $requirements.TPM -and $requirements.Virtualization -and ` - $requirements.Windows11 + $requirements.TPM -and $requirements.Virtualization -and ` + $requirements.Windows11 return [PSCustomObject]@{ - Capable = $allMet - UEFI = $requirements.UEFI - SecureBoot = $requirements.SecureBoot - TPM = $requirements.TPM + Capable = $allMet + UEFI = $requirements.UEFI + SecureBoot = $requirements.SecureBoot + TPM = $requirements.TPM Virtualization = $requirements.Virtualization - Windows11 = $requirements.Windows11 + Windows11 = $requirements.Windows11 } } @@ -90,13 +90,13 @@ function Get-CPUInfo { $cpu = Get-CimInstance -ClassName Win32_Processor -ErrorAction Stop | Select-Object -First 1 return [PSCustomObject]@{ - Name = $cpu.Name - Manufacturer = $cpu.Manufacturer - Cores = $cpu.NumberOfCores - LogicalProcessors = $cpu.NumberOfLogicalProcessors - MaxClockSpeed = $cpu.MaxClockSpeed + Name = $cpu.Name + Manufacturer = $cpu.Manufacturer + Cores = $cpu.NumberOfCores + LogicalProcessors = $cpu.NumberOfLogicalProcessors + MaxClockSpeed = $cpu.MaxClockSpeed VirtualizationEnabled = $cpu.VirtualizationFirmwareEnabled - Architecture = $cpu.Architecture + Architecture = $cpu.Architecture } } catch { @@ -123,9 +123,9 @@ function Get-MemoryInfo { return [PSCustomObject]@{ TotalPhysicalMemoryGB = [math]::Round($cs.TotalPhysicalMemory / 1GB, 2) - FreePhysicalMemoryGB = [math]::Round($os.FreePhysicalMemory / 1MB / 1024, 2) - TotalVirtualMemoryGB = [math]::Round($os.TotalVirtualMemorySize / 1MB / 1024, 2) - FreeVirtualMemoryGB = [math]::Round($os.FreeVirtualMemory / 1MB / 1024, 2) + FreePhysicalMemoryGB = [math]::Round($os.FreePhysicalMemory / 1MB / 1024, 2) + TotalVirtualMemoryGB = [math]::Round($os.TotalVirtualMemorySize / 1MB / 1024, 2) + FreeVirtualMemoryGB = [math]::Round($os.FreeVirtualMemory / 1MB / 1024, 2) } } catch { @@ -192,16 +192,16 @@ function Get-WindowsEditionInfo { $supportsBitLocker = -not $isHome return [PSCustomObject]@{ - Caption = $os.Caption - Version = $os.Version - BuildNumber = $os.BuildNumber - IsHome = $isHome - IsPro = $isPro - IsEnterprise = $isEnterprise - IsEducation = $isEducation + Caption = $os.Caption + Version = $os.Version + BuildNumber = $os.BuildNumber + IsHome = $isHome + IsPro = $isPro + IsEnterprise = $isEnterprise + IsEducation = $isEducation SupportsCredentialGuard = $supportsCredentialGuard - SupportsAppLocker = $supportsAppLocker - SupportsBitLocker = $supportsBitLocker + SupportsAppLocker = $supportsAppLocker + SupportsBitLocker = $supportsBitLocker } } catch { @@ -223,16 +223,16 @@ function Get-HardwareReport { param() return [PSCustomObject]@{ - OS = Get-WindowsVersion - Edition = Get-WindowsEditionInfo - CPU = Get-CPUInfo - Memory = Get-MemoryInfo - UEFI = Test-UEFIBoot - SecureBoot = Test-SecureBootEnabled - TPM = Test-TPMAvailable + OS = Get-WindowsVersion + Edition = Get-WindowsEditionInfo + CPU = Get-CPUInfo + Memory = Get-MemoryInfo + UEFI = Test-UEFIBoot + SecureBoot = Test-SecureBootEnabled + TPM = Test-TPMAvailable Virtualization = Test-VirtualizationEnabled - VBSCapable = Test-VBSCapable - SSD = Test-SSDDrive + VBSCapable = Test-VBSCapable + SSD = Test-SSDDrive } } diff --git a/Utils/Registry.ps1 b/Utils/Registry.ps1 index 1d80a70..b9da902 100644 --- a/Utils/Registry.ps1 +++ b/Utils/Registry.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> diff --git a/Utils/Service.ps1 b/Utils/Service.ps1 index 898c4d2..b225000 100644 --- a/Utils/Service.ps1 +++ b/Utils/Service.ps1 @@ -8,7 +8,7 @@ .NOTES Author: NexusOne23 - Version: 2.2.2 + Version: 2.2.3 Requires: PowerShell 5.1+ #> @@ -213,12 +213,12 @@ function Get-ServiceStatus { $serviceWmi = Get-CimInstance -ClassName Win32_Service -Filter "Name='$ServiceName'" -ErrorAction Stop return [PSCustomObject]@{ - Name = $service.Name + Name = $service.Name DisplayName = $service.DisplayName - Status = $service.Status - StartType = $service.StartType - StartMode = $serviceWmi.StartMode - PathName = $serviceWmi.PathName + Status = $service.Status + StartType = $service.StartType + StartMode = $serviceWmi.StartMode + PathName = $serviceWmi.PathName Description = $serviceWmi.Description } } diff --git a/config.json b/config.json index 34183c1..5c42d3d 100644 --- a/config.json +++ b/config.json @@ -1,5 +1,5 @@ { - "version": "2.2.2", + "version": "2.2.3", "modules": { "SecurityBaseline": { "enabled": true, @@ -48,7 +48,7 @@ "description": "Microsoft Edge v139 Security Baseline: 24 security policies", "_comment": "Interactive: Allow extensions (Y/N, default: Y)", "allowExtensions": true, - "version": "2.2.2", + "version": "2.2.3", "baseline": "Edge v139", "policies": 24, "features": { @@ -75,7 +75,7 @@ "disableWirelessDisplay": false, "disableDiscoveryProtocols": true, "disableIPv6": false, - "version": "2.2.2", + "version": "2.2.3", "policies": 50, "features": { "rdp_hardening": true, @@ -94,7 +94,11 @@ "firewall_shields_up": true, "ipv6_disable": true }, - "profiles": ["Balanced", "Enterprise", "Maximum"] + "profiles": [ + "Balanced", + "Enterprise", + "Maximum" + ] } }, "options": { @@ -106,4 +110,4 @@ "autoConfirm": false, "_comment": "nonInteractive=true: Skip all Read-Host prompts, use config values instead" } -} +} \ No newline at end of file