<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Set the assignedTo field to me in the ADO template first.  <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] **Closes:** #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
9.6 KiB
Fuzzing Testing in PowerToys
Overview
Fuzzing is an automated testing technique that helps identify vulnerabilities and bugs by feeding random, invalid, or unexpected data into the application. This is especially important for PowerToys modules that handle file input/output or user input, such as Hosts File Editor, Registry Preview, and others.
PowerToys integrates Microsoft's OneFuzz service to systematically discover edge cases and unexpected behaviors that could lead to crashes or security vulnerabilities. Fuzzing testing is a requirement from the security team to ensure robust and secure modules.
Why Fuzzing Matters
- Security Enhancement: Identifies potential security vulnerabilities before they reach production
- Stability Improvement: Discovers edge cases that might cause crashes
- Automated Bug Discovery: Finds bugs that traditional testing might miss
- Reduced Manual Testing: Automates the process of testing with unusual inputs
Types of Fuzzing in PowerToys
PowerToys supports two types of fuzzing depending on the module's implementation language:
Setting Up .NET Fuzzing Tests
Step 1: Add a Fuzzing Test Project
Create a new test project within your module folder. Ensure the project name follows the format *.FuzzTests
.
Step 2: Configure the Project
-
Set up a
.NET 8 (Windows)
project- Note: OneFuzz currently supports only .NET 8 projects. The Fuzz team is working on .NET 9 support.
-
Add the required files to your fuzzing test project:
- Create fuzzing test code
- Add
OneFuzzConfig.json
configuration file
Step 3: Configure OneFuzzConfig.json
The OneFuzzConfig.json
file provides critical information for deploying fuzzing jobs. For detailed guidance, see the OneFuzzConfig V3 Documentation.
{
"fuzzers": [
{
"name": "YourModuleFuzzer",
"fuzzerLibrary": "libfuzzer-dotnet",
"targetAssembly": "YourModule.FuzzTests.dll",
"targetClass": "YourModule.FuzzTests.FuzzTestClass",
"targetMethod": "FuzzTest",
"FuzzingTargetBinaries": [
"YourModule.FuzzTests.dll"
]
}
],
"adoTemplate": [
{
"AssignedTo": "leilzh@microsoft.com",
"jobNotificationEmail": "PowerToys@microsoft.com"
}
],
"oneFuzzJobs": [
{
"projectName": "PowerToys",
"targetName": "YourModule",
"jobDependencies": {
"binaries": [
"PowerToys\\x64\\Debug\\tests\\YourModule.FuzzTests\\net8.0-windows10.0.19041.0\\**"
]
}
}
],
"configVersion": "3.0.0"
}
Key fields to update:
- Update the
targetAssembly
,targetClass
,targetMethod
, andFuzzingTargetBinaries
fields - Set the
AssignedTo
andjobNotificationEmail
to your Microsoft email - Update the
projectName
andtargetName
fields - Define job dependencies pointing to your compiled fuzzing tests
Step 4: Configure the OneFuzz Pipeline
Modify the patterns in the job steps within job-fuzz.yml to match your fuzzing project name:
- download: current
displayName: Download artifacts
artifact: $(ArtifactName)
patterns: |-
**/tests/*.FuzzTests/**
Setting Up C++ Fuzzing Tests
Step 1: Create a New C++ Project
- Use the Empty Project template
- Name it
<ModuleName>.FuzzingTest
Step 2: Update Build Configuration
- In Configuration Manager, uncheck Build for both Release|ARM64, Debug|ARM64 and Debug|x64 configurations
- ARM64 is not supported for fuzzing tests
Step 3: Enable ASan and libFuzzer in .vcxproj
Edit the project file to enable fuzzing:
<PropertyGroup>
<EnableASAN>true</EnableASAN>
<EnableFuzzer>true</EnableFuzzer>
</PropertyGroup>
Step 4: Add Fuzzing Compiler Flags
Add these to AdditionalOptions
under the Fuzzing
configuration:
/fsanitize=address
/fsanitize-coverage=inline-8bit-counters
/fsanitize-coverage=edge
/fsanitize-coverage=trace-cmp
/fsanitize-coverage=trace-div
%(AdditionalOptions)
Step 5: Link the Sanitizer Coverage Runtime
In Linker → Input → Additional Dependencies
, add:
$(VCToolsInstallDir)lib\$(Platform)\libsancov.lib
Step 6: Copy Required Runtime DLL
Add a PostBuildEvent
to copy the ASAN DLL:
<Command>
xcopy /y "$(VCToolsInstallDir)bin\Hostx64\x64\clang_rt.asan_dynamic-x86_64.dll" "$(OutDir)"
</Command>
Step 7: Add Preprocessor Definitions
To avoid annotation issues, add these to the Preprocessor Definitions
:
_DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION
Step 8: Implement the Entry Point
Every C++ fuzzing project must expose this function:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
std::string input(reinterpret_cast<const char*>(data), size);
try
{
// Call your module with the input here
}
catch (...) {}
return 0;
}
Running Fuzzing Tests
Running Locally (.NET)
To run .NET fuzzing tests locally, follow the Running a .NET Fuzz Target Locally guide:
# Instrument the assembly
.\dotnet-fuzzing-windows\sharpfuzz\SharpFuzz.CommandLine.exe path\to\YourModule.FuzzTests.dll
# Set environment variables
$env:LIBFUZZER_DOTNET_TARGET_ASSEMBLY="path\to\YourModule.FuzzTests.dll"
$env:LIBFUZZER_DOTNET_TARGET_CLASS="YourModule.FuzzTests.FuzzTestClass"
$env:LIBFUZZER_DOTNET_TARGET_METHOD="FuzzTest"
# Run the fuzzer
.\dotnet-fuzzing-windows\libfuzzer-dotnet\libfuzzer-dotnet.exe --target_path=dotnet-fuzzing-windows\LibFuzzerDotnetLoader\LibFuzzerDotnetLoader.exe
Running in the Cloud
To submit a job to the OneFuzz cloud service, follow the OneFuzz Cloud Testing Walkthrough:
-
Run the pipeline:
- Navigate to the fuzzing pipeline
- Click "Run pipeline"
- Choose your branch and start the run
-
Alternative: Use OIP (OneFuzz Ingestion Preparation) tool:
oip submit --config .\OneFuzzConfig.json --drop-path <your_submission_directory> --platform windows --do-not-file-bugs --duration 1
- Use
--do-not-file-bugs
to prevent automatic bug creation during initial testing --duration
specifies the number of hours (default is 48 if not specified)
- Use
-
OneFuzz will send you an email when the job has started with a link to view results
Reviewing Results
- You'll receive an email notification when your fuzzing job starts
- Click the link in the email to view the job status on the OneFuzz Web UI
- The OneFuzz platform will show statistics like inputs processed, coverage, and any crashes found
- If the final status is "success," your fuzzing test is working correctly
Current Status
PowerToys has implemented fuzzing for several modules:
- Hosts File Editor
- Registry Preview
- Fancy Zones
Modules that still need fuzzing implementation:
- Environmental Variables
- Keyboard Manager
Requesting Access to OneFuzz
To log into the production instance of OneFuzz with the CLI, you must request access. Visit the OneFuzz Access Request Page.