SharpFuzz is a tool that brings the power of afl-fuzz to .NET platform. If you want to learn more about fuzzing, my motivation for writing SharpFuzz, the types of bugs it can find, or the technical details about how the integration with afl-fuzz works, read my blog post SharpFuzz: Bringing the power of afl-fuzz to .NET platform.
- CVE-2019-0980: .NET Framework and .NET Core Denial of Service Vulnerability
- CVE-2019-0981: .NET Framework and .NET Core Denial of Service Vulnerability
- CVE-2025-11573: Denial of Service issue in Amazon.IonDotnet
- SharpFuzz: Bringing the power of afl-fuzz to .NET platform
- Five years of fuzzing .NET with SharpFuzz
- Let’s do DHCP: fuzzing
- Fuzzing C# on Windows with SharpFuzz and libfuzzer-dotnet
- Automate Bug Finding: Fuzzing C# Code on Windows
- Fuzzing .NET Libraries with AFL++ and SharpFuzz
If you find some interesting bugs with SharpFuzz, and are comfortable with sharing them, I would love to add them to this list. Please send me an email, make a pull request for the README file, or file an issue.
- AngleSharp: HtmlParser.Parse throws InvalidOperationExceptionfixed
- AngleSharp: HtmlParser.ParseDocument throws IndexOutOfRangeExceptionfixed
- AngleSharp: HtmlParser.ParseDocument throws InvalidOperationExceptionfixed
- AngleSharp: HtmlParser.ParseDocument hangs permanentlyfixed
- CoreFX: BigInteger.TryParse out-of-bounds accessfixed
- CoreFX: BinaryFormatter.Deserialize throws many unexpected exceptionsfixed
- CoreFX: DataContractJsonSerializer.ReadObject throws ArgumentOutOfRangeException
- CoreFX: DataContractJsonSerializer.ReadObject throws IndexOutOfRangeException
- CoreFX: DataContractSerializer.ReadObject throws ArgumentNullException
- CoreFX: Double.Parse throws AccessViolationException on .NET Core 3.0fixed
- CoreFX: G17 format specifier doesn't always round-trip double valuesfixed
- CoreFX: Uri.TryCreate throws IndexOutOfRangeException
- CoreFX: XmlReader.Create throws IndexOutOfRangeExceptionfixed
- DotLiquid: Template.Parse throws ArgumentNullException instead of SyntaxException
- Esprima .NET: JavaScriptParser.ParseProgram throws ArgumentOutOfRangeExceptionfixed
- Esprima .NET: StackOverflowException when parsing a lot of starting parenthesesfixed
- ExcelDataReader: ExcelReaderFactory.CreateBinaryReader can throw unexpected exceptionsfixed
- ExcelDataReader: ExcelReaderFactory.CreateBinaryReader throws OutOfMemoryExceptionfixed
- ExCSS: StylesheetParser.Parse throws ArgumentOutOfRangeExceptionfixed
- Fluid: FluidTemplate.TryParse and FluidTemplateExtensions.Render throw some unexpected exceptionsfixed
- Fluid: FluidTemplateExtensions.Render hangs permanentlyfixed
- Google.Protobuf: MessageParser.ParseFrom throws unexpected exceptions (C#)fixed
- GraphQL-Parser: Parser.Parse takes around 18s to parse the 58K filefixed
- GraphQL-Parser: Parser.Parse throws ArgumentOutOfRangeExceptionfixed
- Handlebars.Net: Handlebars.Compile hangs permanentlyfixed
- Handlebars.Net: Template engine throws some unexpected exceptionsfixed
- Jil: JSON.DeserializeDynamic throws ArgumentExceptionfixed
- Jint: Engine.Execute can throw many unexpected exceptionsfixed
- Jint: Engine.Execute takes more than two minutes to complete (even with the 2s timeout)fixed
- Jint: Engine.Execute throws OutOfMemoryException after 45s (even with the 2s timeout)fixed
- Json.NET: JsonConvert.DeserializeObject can throw several unexpected exceptionsfixed
- Jurassic: ScriptEngine.Execute terminates the process with StackOverflowException
- Jurassic: ScriptEngine.Execute throws some unexpected exceptionsfixed
- Jurassic: ScriptEngine.ExecuteFile hangs permanently instead of throwing JavaScriptExceptionfixed
- Jurassic: ScriptEngine.ExecuteFile throws FormatExceptionfixed
- LumenWorks CSV Reader: CsvReader.ReadNextRecord throws IndexOutOfRangeException
- Markdig: Markdown.ToHtml hangs permanentlyfixed
- Markdig: Markdown.ToHtml takes more than two minutes to complete when processing the 32K filefixed
- Markdig: Markdown.ToHtml throws ArgumentOutOfRangeExceptionfixed
- Markdig: Markdown.ToHtml throws IndexOutOfRangeExceptionfixed
- Markdig: Markdown.ToHtml throws IndexOutOfRangeExceptionfixed
- Markdig: Markdown.ToHtml throws IndexOutOfRangeException for lastBlock in GetCurrentDefinitionListfixed
- Markdig: Markdown.ToHtml throws IndexOutOfRangeException in StringSlice.NextChar()fixed
- Markdig: Markdown.ToHtml throws InvalidOperationException "A block is already being replaced"fixed
- Markdig: Markdown.ToHtml throws NullReferenceExceptionfixed
- Markdig: StackOverflowException is throw when converting special markdown to HTMLfixed
- MarkdownSharp: Markdown.Transform hangs permanently
- MemoryPack: AcessViolationException from MemoryPackReader.ReadString
- MessagePack for C#: MessagePackSerializer.Deserialize hangs permanentlyfixed
- MessagePack for CLI: Unpacking.UnpackObject throws several unexpected exceptions
- Mono.Cecil: ModuleDefinition.ReadModule can throw many (possibly) unexpected exceptions
- Mono.Cecil: ModuleDefinition.ReadModule hangs permanentlyfixed
- NCrontab: CrontabSchedule.Parse throws OverflowException instead of CrontabException
- nHapi: Bad inputs cause unexpected exceptions and permanent hangfixed
- nHapi: Bad inputs cause StackOverflow/Access Violationfixed
- NoStringEvaluating: Evaluator.Calc throws several unexpected exceptionsfixed
- NUglify: Uglify.Js hangs permanentlyfixed
- Open XML SDK: Add some security/fuzz testing
- OpenMCDF: OutOfMemoryException when parsing Excel document / endless while-loopfixed
- OpenMCDF: System.ArgumentOutOfRangeException take 2fixed
- OpenMCDF: System.ArgumentOutOfRangeException when trying to open certain invalid filesfixed
- OpenMCDF: System.OutOfMemoryException when reading corrupt Word documentfixed
- PdfPig: StackOverflowException reading corrupt PDF documentfixed
- protobuf-net: Serializer.Deserialize can throw many unexpected exceptions
- protobuf-net: Serializer.Deserialize hangs permanentlyfixed
- Scriban: Template.ParseLiquid throws ArgumentOutOfRangeExceptionfixed
- Scriban: Template.ParseLiquid throws NullReferenceExceptionfixed
- Scriban: Template.Render throws InvalidCastExceptionfixed
- SharpCompress: Enumerating ZipArchive.Entries collection throws NullReferenceException
- SharpZipLib: ZipInputStream.GetNextEntry hangs permanentlyfixed
- SixLabors.Fonts: FontDescription.LoadDescription throws ArgumentExceptionfixed
- SixLabors.Fonts: FontDescription.LoadDescription throws NullReferenceExceptionfixed
- SixLabors.ImageSharp: Handle EOF in Jpeg bit reader when data is bad to prevent DOS attackfixed
- SixLabors.ImageSharp: Image.Load terminates the process with AccessViolationExceptionfixed
- SixLabors.ImageSharp: Image.Load throws AccessViolationExceptionfixed
- SixLabors.ImageSharp: Image.Load throws ArgumentExceptionfixed
- SixLabors.ImageSharp: Image.Load throws ArgumentOutOfRangeExceptionfixed
- SixLabors.ImageSharp: Image.Load throws DivideByZeroExceptionfixed
- SixLabors.ImageSharp: Image.Load throws DivideByZeroExceptionfixed
- SixLabors.ImageSharp: Image.Load throws ExecutionEngineExceptionfixed
- SixLabors.ImageSharp: Image.Load throws IndexOutOfRangeExceptionfixed
- SixLabors.ImageSharp: Image.Load throws NullReferenceExceptionfixed
- SixLabors.ImageSharp: Image.Load throws NullReferenceExceptionfixed
- Utf8Json: JsonSerializer.Deserialize can throw many unexpected exceptions
- Web Markup Minifier: HtmlMinifier.Minify hangs permanentlyfixed
- Web Markup Minifier: HtmlMinifier.Minify throws InvalidOperationExceptionfixed
- YamlDotNet: YamlStream.Load takes more than 60s to parse the 37K file
- YamlDotNet: YamlStream.Load terminates the process with StackOverflowException
- YamlDotNet: YamlStream.Load throws ArgumentException
AFL works on Linux and macOS. If you are using Windows, you can use any Linux distribution that works under the Windows Subsystem for Linux. For native Windows support, you can use libFuzzer instead of AFL.
You will need GNU make and a working compiler (gcc or clang) in order to compile afl-fuzz. You will also need to have the .NET 8.0 or greater installed on your machine in order to instrument .NET assemblies with SharpFuzz.
To simplify your fuzzing experience, it's also recommended to install PowerShell.
You can install afl-fuzz and SharpFuzz.CommandLine global .NET tool by running the following script:
#/bin/shset -eux
# Download and extract the latest afl-fuzz source package
wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
tar -xvf afl-latest.tgz
rm afl-latest.tgz
cd afl-2.53b/
# Install afl-fuzz
sudo make install
cd ..
rm -rf afl-2.53b/
# Install SharpFuzz.CommandLine global .NET tool
dotnet tool install --global SharpFuzz.CommandLineThis tutorial assumes that you are somewhat familiar with afl-fuzz. If you don't know anything about it, you should first read the AFL quick start guide and the afl-fuzz README. If you have enough time, I would also recommend reading Understanding the status screen and Technical whitepaper for afl-fuzz.
As an example, we are going to fuzz Jil, which is a fast JSON serializer and deserializer (see SharpFuzz.Samples for many more examples of complete fuzzing projects).
1. Create a new .NET console project, then add Jil and SharpFuzz packages to it by running the following commands:
dotnet add package Jil
dotnet add package SharpFuzz2. In your Main function, call SharpFuzz.Fuzzer.OutOfProcess.Run with the function that you want to test as a parameter:
usingSystem;usingSystem.IO;usingSharpFuzz;namespaceJil.Fuzz{publicclassProgram{publicstaticvoidMain(string[]args){Fuzzer.OutOfProcess.Run(stream =>{try{using(varreader=newStreamReader(stream)){JSON.DeserializeDynamic(reader);}}catch(DeserializationException){}});}}}We want to fuzz the deserialization capabilities of Jil, which is why we are calling the JSON.DeserializeDynamic method. The input data will be provided to us via the stream parameter (if the code you are testing takes its input as a string, you can use an additional overload of Fuzzer.OutOfProcess.Run that accepts Action<string>).
If the code passed to Fuzzer.OutOfProcess.Run throws an exception, it will be reported to afl-fuzz as a crash. However, we want to treat only unexpected exceptions as bugs. DeserializationException is what we expect when we encounter an invalid JSON input, which is why we catch it in our example.
3. Create a directory with some test cases (one test is usually more than enough). Test files should contain some input that is accepted by your code as valid, and should also be as small as possible. For example, this is the JSON I'm using for testing JSON deserializers:
{"menu":{"id":1,"val":"X","pop":{"a":[{"click":"Open()"},{"click":"Close()"}]}}}4. Let's say that your project is called Fuzzing.csproj
and that your test cases are in the Testcases directory.
Start fuzzing by running the fuzz.ps1 script like this:
pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i TestcasesFor formats such as HTML, JavaScript, JSON, or SQL,
the fuzzing process can be greatly improved with
the usage of a dictionary file. AFL comes with
bunch of dictionaries, which you can find after
installation in /usr/local/share/afl/dictionaries/.
With this in mind, we can improve our fuzzing of Jil like this:
pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i Testcases \
-x /usr/local/share/afl/dictionaries/json.dict5. Sit back and relax! You will often have some useful results within minutes, but sometimes it can take more than a day, so be patient.
The input files responsible for unhandled exceptions will
appear in the findings/crashes directory. The total
number of unique crashes will be displayed in red on the
afl-fuzz status screen.
In practice, the real number of unique exceptions will often be much lower than the reported number, which is why it's usually best to write a small program that just goes through the crashing inputs, runs the fuzzing function on each of them, and saves only the inputs that produce unique stack traces.
- Fuzzing .NET Core
- Out-of-process fuzzing
- Test case minimization
- Using libFuzzer with SharpFuzz
- Legacy usage instructions
- Joe Ranweiler and the MORSE team - libFuzzer support on Windows
- Michal Zalewski - american fuzzy lop
- Dmitry Vyukov - go-fuzz: randomized testing for Go
- Rody Kersten - Kelinci: AFL-based fuzzing for Java
- Jb Evain - Mono.Cecil
- 0xd4d - dnlib
- Guido Vranken - go-fuzz: libFuzzer support