Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/env-matrix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Environment Compatibility Matrix

on:
push:
branches: [ "🌕Nextgen", "📦Current" ]
pull_request:
branches: [ "🌕Nextgen", "📦Current" ]

jobs:
matrix-test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-2019, windows-2022]
shell: [pwsh, powershell]
admin: [true, false]
locale: [en-US, de-DE]
name: Env: ${{ matrix.os }} | Shell: ${{ matrix.shell }} | Admin: ${{ matrix.admin }} | Locale: ${{ matrix.locale }}
steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Set locale
run: |
Set-WinSystemLocale ${{ matrix.locale }}
shell: powershell
continue-on-error: true

- name: Run as admin (if required)
if: ${{ matrix.admin == 'true' }}
run: |
Start-Process -FilePath ${{ matrix.shell }} -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File windows-telemetry-blocker.ps1 -dryrun' -Verb RunAs
shell: powershell
continue-on-error: true

- name: Run as non-admin (if required)
if: ${{ matrix.admin == 'false' }}
run: |
${{ matrix.shell }} -NoProfile -ExecutionPolicy Bypass -File windows-telemetry-blocker.ps1 -dryrun
shell: powershell
continue-on-error: true

- name: Upload logs and report
uses: actions/upload-artifact@v4
with:
name: logs-${{ matrix.os }}-${{ matrix.shell }}-${{ matrix.admin }}-${{ matrix.locale }}
path: |
telemetry-blocker.log
telemetry-blocker-errors.log
telemetry-blocker-report.md
if-no-files-found: ignore
27 changes: 27 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Security Policy

## Supported Versions
- Only the latest release is actively supported for security updates.
- Older versions may not receive security patches.

## Reporting a Vulnerability
If you discover a security vulnerability, please do **not** open a public issue. Instead, report it privately:

- Email: security@n0thorizon.dev (or use GitHub's private vulnerability reporting)
- Include a detailed description, steps to reproduce, and any relevant logs or screenshots.
- We will respond as quickly as possible and coordinate a fix.

## Security Best Practices
- Always download releases from the official repository.
- Review scripts before running, especially if you modify them.
- Run the script in a test environment before deploying to production systems.
- Keep your system and PowerShell up to date.

## Disclosure Policy
- We follow responsible disclosure. Vulnerabilities will be fixed promptly and disclosed after a patch is released.

## Hall of Fame
- Security researchers who responsibly disclose vulnerabilities may be credited here (with permission).

---
For any other security concerns, contact the maintainer directly.
44 changes: 38 additions & 6 deletions modules/common.ps1
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
# Common functions for all modules

# Enhanced Write-ModuleLog: robust fallback, cross-env
function Write-ModuleLog {
param([string]$msg)
if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
Write-Log $msg
try {
if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
Write-Log $msg
} else {
$logFile = Join-Path $PSScriptRoot '..' 'telemetry-blocker.log'
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp $msg" | Out-File -FilePath $logFile -Append -Encoding utf8
}
} catch {
Write-Host "[LOG ERROR] $msg" -ForegroundColor Red
}
}

# Enhanced Set-RegistryValue: supports more types, error handling, cross-env
function Set-RegistryValue {
param($Path, $Name, $Value, $Type = "DWord")
param(
[Parameter(Mandatory)]$Path,
[Parameter(Mandatory)]$Name,
[Parameter(Mandatory)]$Value,
[ValidateSet("DWord","QWord","String","ExpandString","Binary","MultiString")]
[string]$Type = "DWord"
)
if ($global:dryrun) {
Write-Host "[DRY-RUN] Would set $Path\$Name = $Value ($Type)" -ForegroundColor DarkYellow
Write-ModuleLog "[DRY-RUN] Would set $Path\$Name = $Value ($Type)"
Write-ModuleLog "[DRY-RUN] Would set $($Path)\$($Name) = $Value ($Type)"
} else {
Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type
Write-ModuleLog "Set $Path\$Name = $Value ($Type)"
try {
if ($Type -eq "DWord" -or $Type -eq "QWord") {
Set-ItemProperty -Path $Path -Name $Name -Value ([Convert]::ToInt64($Value)) -Type $Type
} elseif ($Type -eq "String" -or $Type -eq "ExpandString") {
Set-ItemProperty -Path $Path -Name $Name -Value "$Value" -Type $Type
} elseif ($Type -eq "Binary") {
Set-ItemProperty -Path $Path -Name $Name -Value ([byte[]]$Value) -Type $Type
} elseif ($Type -eq "MultiString") {
Set-ItemProperty -Path $Path -Name $Name -Value ([string[]]$Value) -Type $Type
} else {
Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type
}
Write-ModuleLog "Set $($Path)\$($Name) = $Value ($Type)"
} catch {
Write-Host "[ERROR] Failed to set $($Path)\$($Name): $_" -ForegroundColor Red
Write-ModuleLog "[ERROR] Failed to set $($Path)\$($Name): $_"
}
}
}
88 changes: 86 additions & 2 deletions run.bat
Original file line number Diff line number Diff line change
@@ -1,10 +1,94 @@
@echo off
:: Windows Telemetry Blocker Launcher (Critical Features Enhanced)
:: Ensures admin, supports spaces in paths, and works from any directory

setlocal
set "SCRIPT_DIR=%~dp0"
set "PS_SCRIPT=%SCRIPT_DIR%windows-telemetry-blocker.ps1"

:: --- Critical: Check for script existence ---
if not exist "%PS_SCRIPT%" (
echo [FATAL] Main PowerShell script not found: %PS_SCRIPT%
echo Please ensure all files are extracted and try again.
pause
exit /b 1
)

:: --- Critical: Print script version if available ---
for /f "tokens=3 delims=' " %%A in ('findstr /C:"$ScriptVersion = '" "%PS_SCRIPT%"') do set SCRIPT_VERSION=%%A
if defined SCRIPT_VERSION (
echo [INFO] Script version: %SCRIPT_VERSION%
)

:: QoL: Clear screen and color title (if supported)
cls
title Windows Telemetry Blocker
echo ===================================
echo Windows Telemetry Blocker
echo ===================================
echo.
echo Starting script with administrator privileges...
echo [INFO] This launcher will ensure you have admin rights and run the script with the best available PowerShell.
echo [INFO] If you see errors, right-click and 'Run as administrator'.
echo [INFO] Logs and reports will be saved in the script folder.
echo.

PowerShell -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dp0windows-telemetry-blocker.ps1""' -Verb RunAs}"
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [WARN] Requesting administrator privileges...
PowerShell -ExecutionPolicy Bypass -Command "Start-Process '%~dpnx0' -Verb RunAs"
exit /b
)

echo [OK] Running with administrator privileges.
echo.

:: --- Critical: Check PowerShell version ---
set "PS_VER_OK=0"
where pwsh >nul 2>&1
if %errorlevel%==0 (
for /f "delims=" %%V in ('pwsh -NoProfile -Command "$PSVersionTable.PSVersion.ToString()"') do set PSVER=%%V
echo [INFO] Using PowerShell Core (pwsh) version %PSVER%...
set "PS_VER_OK=1"
pwsh -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%"
set "PS_EXIT=%ERRORLEVEL%"
) else (
where powershell >nul 2>&1
if %errorlevel%==0 (
for /f "delims=" %%V in ('powershell -NoProfile -Command "$PSVersionTable.PSVersion.ToString()"') do set PSVER=%%V
echo [INFO] Using Windows PowerShell version %PSVER%...
set "PS_VER_OK=1"
powershell -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%"
set "PS_EXIT=%ERRORLEVEL%"
) else (
echo [ERROR] PowerShell is not installed or not in PATH.
pause
exit /b 1
)
)
if "%PS_VER_OK%" == "0" (
echo [FATAL] No compatible PowerShell found.
pause
exit /b 1
)

:: --- Critical: Pause and show result, print log/report if error ---
if "%PS_EXIT%" NEQ "0" (
echo.
echo [ERROR] The script exited with error code %PS_EXIT%.
if exist "%SCRIPT_DIR%telemetry-blocker-errors.log" (
echo --- Error Log ---
type "%SCRIPT_DIR%telemetry-blocker-errors.log"
)
if exist "%SCRIPT_DIR%telemetry-blocker-report.md" (
echo --- Report ---
type "%SCRIPT_DIR%telemetry-blocker-report.md"
)
echo Please check the log and report files for details.
) else (
echo.
echo [SUCCESS] Script completed. Review the report and logs for results.
)
echo.
pause
endlocal
16 changes: 16 additions & 0 deletions telemetry-blocker-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Windows Telemetry Blocker - Change Report

This report will be generated by the script after each run (or dry-run), summarizing all actions taken or that would be taken.

- **Windows Version:**
- **Build Number:**
- **Script Version:**
- **Execution Time:**
- **Modules Run:**
- **Summary:**
- **Errors:**
- **Rollback Modules:**

---

*This file is a template. The script will overwrite or update a file like this after each run.*
76 changes: 73 additions & 3 deletions windows-telemetry-blocker.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ $ScriptVersion = 'nextgen-0.1-DB6'
param(
[switch]$all,
[string[]]$modules,
[string[]]$exclude,
[switch]$interactive,
[switch]$dryrun
[switch]$dryrun,
[switch]$whatif
)

# --- Version Banner ---
Expand All @@ -26,15 +28,43 @@ Write-Host "Script started at: $(Get-Date)" -ForegroundColor Yellow
Write-Host "Running from: $PSScriptRoot" -ForegroundColor Yellow
Write-Host "================================`n"

# Registry backup/export before changes
function Export-RegistryBackup {
$backupDir = Join-Path $PSScriptRoot "registry-backups"
if (-not (Test-Path $backupDir)) { New-Item -ItemType Directory -Path $backupDir | Out-Null }
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$backupFile = Join-Path $backupDir "regbackup_$timestamp.reg"
Write-Host "Exporting registry backup to $backupFile ..." -ForegroundColor Cyan
reg export HKLM $backupFile /y | Out-Null
Write-Host "✓ Registry backup complete." -ForegroundColor Green
}

# Only export backup if not dryrun
if (-not $dryrun) { Export-RegistryBackup }


# Logging setup
$logFile = Join-Path $PSScriptRoot "telemetry-blocker.log"
function Write-Log {
param([string]$msg)
param([string]$msg, [switch]$Error)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp $msg" | Out-File -FilePath $logFile -Append -Encoding utf8
$entry = "$timestamp $msg"
$entry | Out-File -FilePath $logFile -Append -Encoding utf8
if ($Error) {
$errorLogFile = Join-Path $PSScriptRoot "telemetry-blocker-errors.log"
$entry | Out-File -FilePath $errorLogFile -Append -Encoding utf8
}
}

# Log Windows version and build number at the start
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
$winVersion = $osInfo.Version
$winBuild = $osInfo.BuildNumber
Write-Log "=== Script started ==="
Write-Log "Windows Version: $winVersion"
Write-Log "Windows Build: $winBuild"
Write-Log "Script Version: $ScriptVersion"
$reportFile = Join-Path $PSScriptRoot "telemetry-blocker-report.md"

# Check if modules directory exists
$modulesDir = Join-Path $PSScriptRoot "modules"
Expand Down Expand Up @@ -378,6 +408,7 @@ foreach ($mod in $toRunResolved) {
}
}


$endTime = Get-Date
$duration = $endTime - $startTime
Write-Stats "Execution started: $startTime"
Expand Down Expand Up @@ -408,5 +439,44 @@ Write-Host "Error log: $errorLogFile" -ForegroundColor Yellow
if ($rollbackModules.Count -gt 0) {
Write-Host "Rollback modules executed: $($rollbackModules -join ', ')" -ForegroundColor Red
}

# --- Generate Markdown/HTML Report ---
$reportContent = @()
$reportContent += "# Windows Telemetry Blocker - Change Report"
$reportContent += ""
$reportContent += "**Date:** $(Get-Date)"
$reportContent += "**Script Version:** $ScriptVersion"
$reportContent += "**Windows Version:** $winVersion"
$reportContent += "**Windows Build:** $winBuild"
$reportContent += "**Execution Time:** $($duration.ToString())"
$reportContent += ""
$reportContent += "## Modules Run"
$moduleKeys = $moduleResults.Keys
foreach ($mod in $moduleKeys) {
$res = $moduleResults[$mod]
$line = "- $mod $($res.Status) (Start: $($res.Start), End: $($res.End))"
if ($res.Error) { $line += " - Error: $($res.Error)" }
$reportContent += $line
}
$reportContent += ""
$reportContent += "## Summary"
foreach ($item in $summary) {
$reportContent += "- $item"
}
$reportContent += ""
if ($rollbackModules.Count -gt 0) {
$reportContent += "## Rollback Modules"
$reportContent += "- $($rollbackModules -join ', ')"
}
$reportContent += ""
$errors = Get-Content -Path $errorLogFile -ErrorAction SilentlyContinue
if ($errors -and $errors.Count -gt 0) {
$reportContent += "## Errors"
foreach ($err in $errors) { $reportContent += "- $err" }
}

$reportContent | Set-Content -Path $reportFile -Encoding utf8

Write-Host "Report written to: $reportFile" -ForegroundColor Green
Write-Host "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Loading