|
1 | | -<h1><img src="https://raw.githubusercontent.com/AJMitev/FileTypeChecker/master/tools/FileTypeCheckerLogo-150.png" align="left" alt="FileTypeChecker" width="90">FileTypeChecker - Protect your application from malicious files</h1> |
| 1 | +# 🛡️ FileTypeChecker |
2 | 2 |
|
3 | | -[](https://ci.appveyor.com/project/AJMitev/filetypechecker) [](https://www.nuget.org/packages/File.TypeChecker/) [](https://github.com/AJMitev/FileTypeChecker/blob/master/LICENSE) [](https://www.codefactor.io/repository/github/ajmitev/filetypechecker)  |
| 3 | +<div align="center"> |
4 | 4 |
|
5 | | -## Support the project |
| 5 | + |
6 | 6 |
|
7 | | -- If you like this library, ⭐️ the repository and show it to your friends! |
8 | | -- If you find this library usefull and it helps you please consider to support the project, you can do by [buying me a cup of coffee](https://www.buymeacoffee.com/ajmitev). |
9 | | -- If you love this library and want to help me continue maintaining it and also have a direct contact with the developers consider [becoming a member](https://buymeacoffee.com/ajmitev/membership). |
| 7 | +**Secure file type validation for .NET applications using magic number detection** |
10 | 8 |
|
11 | | -<a href="https://www.buymeacoffee.com/ajmitev" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a> |
| 9 | +[](https://ci.appveyor.com/project/AJMitev/filetypechecker) |
| 10 | +[](https://www.nuget.org/packages/File.TypeChecker/) |
| 11 | +[](https://www.nuget.org/packages/File.TypeChecker/) |
| 12 | +[](https://github.com/AJMitev/FileTypeChecker/blob/master/LICENSE) |
| 13 | +[](https://www.codefactor.io/repository/github/ajmitev/filetypechecker) |
| 14 | +[](https://discord.gg/your-discord-invite) |
12 | 15 |
|
13 | | -## Project Description |
| 16 | +</div> |
14 | 17 |
|
15 | | -FileTypeChecker is a easy to use library that provides quality identification of a file type. This will help you to secure your applications by validating all files that are provided by external sources with few lines of code. |
| 18 | +## ✨ Overview |
16 | 19 |
|
17 | | -## Table of Contents |
| 20 | +FileTypeChecker is a powerful .NET library that provides reliable file type identification using magic number detection. Unlike traditional filename extension-based validation, this library analyzes the actual file content to determine the true file type, protecting your applications from malicious files and ensuring robust security. |
18 | 21 |
|
19 | | -[1. Why to use it?](#why-to-use-it) |
| 22 | +## 📋 Table of Contents |
20 | 23 |
|
21 | | -[2. How it works?](#how-it-works) |
| 24 | +- [🚀 Quick Start](#-quick-start) |
| 25 | +- [💡 Why Use FileTypeChecker?](#-why-use-filetypechecker) |
| 26 | +- [⚙️ How It Works](#-how-it-works) |
| 27 | +- [📦 Installation](#-installation) |
| 28 | +- [🔧 Usage Examples](#-usage-examples) |
| 29 | +- [📄 Supported File Types](#-supported-file-types) |
| 30 | +- [🌐 Web Applications](#-web-applications) |
| 31 | +- [🤝 Contributing](#-contributing) |
| 32 | +- [💖 Support the Project](#-support-the-project) |
| 33 | +- [📝 License](#-license) |
22 | 34 |
|
23 | | -[3. How to install?](#how-to-install) |
| 35 | +## 🚀 Quick Start |
24 | 36 |
|
25 | | -[4. How to use?](#how-to-use) |
| 37 | +```csharp |
| 38 | +using (var fileStream = File.OpenRead("suspicious-file.exe")) |
| 39 | +{ |
| 40 | + // Check if file type can be identified |
| 41 | + if (FileTypeValidator.IsTypeRecognizable(fileStream)) |
| 42 | + { |
| 43 | + // Get the actual file type |
| 44 | + IFileType fileType = FileTypeValidator.GetFileType(fileStream); |
| 45 | + Console.WriteLine($"File type: {fileType.Name} ({fileType.Extension})"); |
| 46 | + |
| 47 | + // Check specific type |
| 48 | + bool isImage = fileStream.IsImage(); |
| 49 | + bool isPdf = fileStream.Is<PortableDocumentFormat>(); |
| 50 | + } |
| 51 | +} |
| 52 | +``` |
26 | 53 |
|
27 | | -[5. Web Applications](#web-applications) |
| 54 | +## 💡 Why Use FileTypeChecker? |
28 | 55 |
|
29 | | -## Why to use it? |
| 56 | +### 🎯 The Problem |
| 57 | +Traditional file validation relies on file extensions, which can be easily manipulated: |
| 58 | +- A malicious executable can be renamed to `.jpg` |
| 59 | +- Untrusted files can bypass basic extension checks |
| 60 | +- The `FileSystemInfo.Extension` property only reads the filename |
30 | 61 |
|
31 | | -Have you ever had a requirement for users to be able to upload files of a certain type? How do you validate that the file type is allowed? How do you protect your application from uploading a malicious file? It is standard practice to use the [FileSystemInfo](https://docs.microsoft.com/en-us/dotnet/api/system.io.fileinfo?view=netcore-3.1#definition) class provided by Microsoft and its [Extension](https://docs.microsoft.com/en-us/dotnet/api/system.io.filesysteminfo.extension?view=netcore-3.1#System_IO_FileSystemInfo_Extension) property for this kind of job, but is that enough? The answer is simple - No! This is why this small but effective library comes to help. |
| 62 | +### ✅ The Solution |
| 63 | +FileTypeChecker analyzes the actual file content using magic numbers: |
| 64 | +- **Reliable**: Identifies files by their binary signature, not filename |
| 65 | +- **Secure**: Prevents malicious files from masquerading as safe formats |
| 66 | +- **Comprehensive**: Supports 30+ file types with extensible architecture |
| 67 | +- **Fast**: Minimal performance overhead with efficient binary analysis |
32 | 68 |
|
33 | | -## How it works? |
| 69 | +## ⚙️ How It Works |
34 | 70 |
|
35 | | -FileTypeChecker use file's "magic numbers" to identify the type. According to Wikipedia this term ("magic numbers") was used for a specific set of 2-byte identifiers at the beginnings of files, but since any binary sequence can be regarded as a number, any feature of a file format which uniquely distinguishes it can be used for identification. This approach offers better guarantees that the format will be identified correctly, and can often determine more precise information about the file. [See more about Magic Numbers](https://en.wikipedia.org/wiki/File_format#Magic_number) |
| 71 | +FileTypeChecker uses **magic numbers** (binary signatures) to identify file types. These are specific byte sequences found at the beginning of files that uniquely identify the format. |
36 | 72 |
|
37 | | -## How to install? |
| 73 | +### 🔍 Magic Number Examples |
| 74 | +``` |
| 75 | +PDF: 25 50 44 46 (%PDF) |
| 76 | +PNG: 89 50 4E 47 (‰PNG) |
| 77 | +JPEG: FF D8 FF (ÿØÿ) |
| 78 | +ZIP: 50 4B 03 04 (PK..) |
| 79 | +``` |
38 | 80 |
|
39 | | -You can install this library using NuGet into your project. |
| 81 | +This method provides reliable identification regardless of file extension, offering better security guarantees than filename-based validation. |
40 | 82 |
|
41 | | -```nuget |
| 83 | +> 📖 Learn more about [Magic Numbers on Wikipedia](https://en.wikipedia.org/wiki/File_format#Magic_number) |
| 84 | +
|
| 85 | +## 📦 Installation |
| 86 | + |
| 87 | +### Package Manager |
| 88 | +```powershell |
42 | 89 | Install-Package File.TypeChecker |
43 | 90 | ``` |
44 | 91 |
|
45 | | -or by using dotnet CLI |
| 92 | +### .NET CLI |
| 93 | +```bash |
| 94 | +dotnet add package File.TypeChecker |
| 95 | +``` |
46 | 96 |
|
| 97 | +### PackageReference |
| 98 | +```xml |
| 99 | +<PackageReference Include="File.TypeChecker" Version="4.2.0" /> |
47 | 100 | ``` |
48 | | -dotnet add package File.TypeChecker |
| 101 | + |
| 102 | +**Requirements**: .NET Standard 2.0+ |
| 103 | + |
| 104 | +## 🔧 Usage Examples |
| 105 | + |
| 106 | +### Basic File Type Detection |
| 107 | +```csharp |
| 108 | +using FileTypeChecker; |
| 109 | + |
| 110 | +using (var fileStream = File.OpenRead("document.pdf")) |
| 111 | +{ |
| 112 | + // Check if file type is recognizable |
| 113 | + if (FileTypeValidator.IsTypeRecognizable(fileStream)) |
| 114 | + { |
| 115 | + // Get file type information |
| 116 | + IFileType fileType = FileTypeValidator.GetFileType(fileStream); |
| 117 | + Console.WriteLine($"Type: {fileType.Name}"); |
| 118 | + Console.WriteLine($"Extension: {fileType.Extension}"); |
| 119 | + } |
| 120 | +} |
49 | 121 | ``` |
50 | 122 |
|
51 | | -## How to use? |
| 123 | +### Category-Based Validation |
| 124 | +```csharp |
| 125 | +using (var fileStream = File.OpenRead("image.jpg")) |
| 126 | +{ |
| 127 | + // Check by category |
| 128 | + bool isImage = fileStream.IsImage(); |
| 129 | + bool isDocument = fileStream.IsDocument(); |
| 130 | + bool isArchive = fileStream.IsArchive(); |
| 131 | + |
| 132 | + // Check specific type |
| 133 | + bool isPng = fileStream.Is<PortableNetworkGraphic>(); |
| 134 | + bool isJpeg = fileStream.Is<JointPhotographicExpertsGroup>(); |
| 135 | +} |
| 136 | +``` |
52 | 137 |
|
53 | | -```c# |
54 | | -using (var fileStream = File.OpenRead("myFileLocation")) |
| 138 | +### File Upload Validation |
| 139 | +```csharp |
| 140 | +public bool ValidateUploadedFile(IFormFile file) |
55 | 141 | { |
56 | | - var isRecognizableType = FileTypeValidator.IsTypeRecognizable(fileStream); |
| 142 | + using (var stream = file.OpenReadStream()) |
| 143 | + { |
| 144 | + // Verify file is actually an image (regardless of file extension) |
| 145 | + if (!stream.IsImage()) |
| 146 | + { |
| 147 | + throw new InvalidOperationException("Only image files are allowed"); |
| 148 | + } |
| 149 | + |
| 150 | + // Additional validation for specific formats |
| 151 | + var fileType = FileTypeValidator.GetFileType(stream); |
| 152 | + var allowedTypes = new[] { "PNG", "JPEG", "BMP" }; |
| 153 | + |
| 154 | + return allowedTypes.Contains(fileType.Name); |
| 155 | + } |
| 156 | +} |
| 157 | +``` |
57 | 158 |
|
58 | | - if (!isRecognizableType) |
| 159 | +### Custom File Type Registration |
| 160 | +```csharp |
| 161 | +// Register your own file type |
| 162 | +public class MyCustomType : FileType |
| 163 | +{ |
| 164 | + public override string Name => "My Custom Format"; |
| 165 | + public override string Extension => "mycustom"; |
| 166 | + public override string MimeType => "application/x-mycustom"; |
| 167 | + |
| 168 | + public override bool IsMatch(byte[] signature, Stream stream) |
59 | 169 | { |
60 | | - // Do something ... |
| 170 | + return signature.Length >= 4 && |
| 171 | + signature[0] == 0x4D && signature[1] == 0x59 && |
| 172 | + signature[2] == 0x43 && signature[3] == 0x54; |
61 | 173 | } |
| 174 | +} |
| 175 | + |
| 176 | +// Use it |
| 177 | +FileTypeValidator.RegisterType<MyCustomType>(); |
| 178 | +``` |
| 179 | + |
| 180 | +> 📚 More examples available in our [Wiki](https://github.com/AJMitev/FileTypeChecker/wiki/How-to-use%3F) |
| 181 | +
|
| 182 | +## 📄 Supported File Types |
| 183 | + |
| 184 | +FileTypeChecker supports **30+ file formats** across multiple categories: |
| 185 | + |
| 186 | +### 🖼️ Images |
| 187 | +- **PNG** - Portable Network Graphics |
| 188 | +- **JPEG** - Joint Photographic Experts Group |
| 189 | +- **GIF** - Graphics Interchange Format (87a/89a) |
| 190 | +- **BMP** - Bitmap Image File |
| 191 | +- **TIFF** - Tagged Image File Format |
| 192 | +- **WebP** - WebP Image Format |
| 193 | +- **ICO** - Icon File |
| 194 | +- **PSD** - Photoshop Document |
| 195 | +- **HEIC** - High Efficiency Image Container |
| 196 | + |
| 197 | +### 📄 Documents |
| 198 | +- **PDF** - Portable Document Format |
| 199 | +- **DOC/DOCX** - Microsoft Word Documents |
| 200 | +- **XLS/XLSX** - Microsoft Excel Spreadsheets |
| 201 | +- **HTML** - HyperText Markup Language |
| 202 | +- **XML** - Extensible Markup Language |
| 203 | + |
| 204 | +### 🗜️ Archives |
| 205 | +- **ZIP** - ZIP Archive |
| 206 | +- **RAR** - RAR Archive |
| 207 | +- **7Z** - 7-Zip Archive |
| 208 | +- **TAR** - TAR Archive |
| 209 | +- **GZIP** - GNU Zip |
| 210 | +- **BZIP2** - BZIP2 Compressed File |
| 211 | + |
| 212 | +### 🎵 Audio/Video |
| 213 | +- **MP3** - MPEG Audio Layer 3 |
| 214 | +- **MP4** - MPEG-4 Video |
| 215 | +- **M4V** - iTunes Video |
| 216 | +- **AVI** - Audio Video Interleave |
| 217 | +- **WAV** - Windows Audio |
| 218 | + |
| 219 | +### 💻 Executables |
| 220 | +- **EXE** - Windows Executable |
| 221 | +- **ELF** - Executable and Linkable Format |
62 | 222 |
|
63 | | - IFileType fileType = FileTypeValidator.GetFileType(fileStream); |
64 | | - Console.WriteLine("Type Name: {0}", fileType.Name); |
65 | | - Console.WriteLine("Type Extension: {0}", fileType.Extension); |
66 | | - Console.WriteLine("Is Image?: {0}", fileStream.IsImage()); |
67 | | - Console.WriteLine("Is Bitmap?: {0}", fileStream.Is<Bitmap>()); |
| 223 | +### ➕ Extensible |
| 224 | +Add your own custom file types by implementing the `IFileType` interface. |
| 225 | + |
| 226 | +> 📋 Complete list available in our [Wiki](https://github.com/AJMitev/FileTypeChecker/wiki/What-types-of-file-are-supported%3F) |
| 227 | +
|
| 228 | +## 🌐 Web Applications |
| 229 | + |
| 230 | +For **ASP.NET Core** applications, check out [FileTypeChecker.Web](https://github.com/AJMitev/FileTypeChecker.Web) - a companion package with validation attributes for `IFormFile`: |
| 231 | + |
| 232 | +```csharp |
| 233 | +public class UploadModel |
| 234 | +{ |
| 235 | + [AllowedFileTypes(FileType.Jpeg, FileType.Png)] |
| 236 | + [MaxFileSize(5 * 1024 * 1024)] // 5MB |
| 237 | + public IFormFile ProfileImage { get; set; } |
68 | 238 | } |
69 | 239 | ``` |
70 | 240 |
|
71 | | -If you are interested in finding more samples please use our [wiki page](https://github.com/AJMitev/FileTypeChecker/wiki/How-to-use%3F). |
| 241 | +### Features |
| 242 | +- ✅ Pre-built validation attributes |
| 243 | +- ✅ Model binding integration |
| 244 | +- ✅ Automatic error messages |
| 245 | +- ✅ Easy file upload validation |
| 246 | + |
| 247 | +## 🤝 Contributing |
| 248 | + |
| 249 | +We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details. |
| 250 | + |
| 251 | +### Development |
| 252 | +```bash |
| 253 | +git clone https://github.com/AJMitev/FileTypeChecker.git |
| 254 | +cd FileTypeChecker |
| 255 | +dotnet restore |
| 256 | +dotnet build |
| 257 | +dotnet test |
| 258 | +``` |
| 259 | + |
| 260 | +## 💖 Support the Project |
| 261 | + |
| 262 | +If this library helps you, consider supporting its development: |
| 263 | + |
| 264 | +- ⭐ **Star the repository** and share it with others |
| 265 | +- ☕ [**Buy me a coffee**](https://www.buymeacoffee.com/ajmitev) for continued development |
| 266 | +- 👥 [**Become a member**](https://buymeacoffee.com/ajmitev/membership) for direct access to maintainers |
72 | 267 |
|
73 | | -## What types of file are supported? |
| 268 | +<a href="https://www.buymeacoffee.com/ajmitev" target="_blank"> |
| 269 | + <img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" height="41" width="174"> |
| 270 | +</a> |
74 | 271 |
|
75 | | -FileTypeChecker is able to identify more than 22 different types but also you are able to register your own types. For more information please visit our [wiki page](https://github.com/AJMitev/FileTypeChecker/wiki/What-types-of-file-are-supported%3F) |
| 272 | +## 📝 License |
76 | 273 |
|
77 | | -## Web Applications |
| 274 | +This project is licensed under the [MIT License](LICENSE) - see the LICENSE file for details. |
78 | 275 |
|
79 | | -If you are developing Web application you can [check this](https://github.com/AJMitev/FileTypeChecker.Web). That package is designed for ASP.NET applications and contains very useful predefined validation attributes that can be used for IFormFile. |
| 276 | +## 🙏 Credits |
80 | 277 |
|
81 | | -## Credits |
| 278 | +- Based on [mjolka](https://github.com/mjolka)'s Stack Overflow answer: [Guessing a file type based on its content](http://codereview.stackexchange.com/questions/85054/guessing-a-file-type-based-on-its-content) |
| 279 | +- Inspired by [0xbrock's FileTypeChecker](https://github.com/0xbrock/FileTypeChecker) |
| 280 | +- Completely rewritten with object-oriented design, fluent API, and extensibility |
82 | 281 |
|
83 | | -Based on [mjolka](https://github.com/mjolka)'s answer to the Stack Overflow question [Guessing a file type based on its content](http://codereview.stackexchange.com/questions/85054/guessing-a-file-type-based-on-its-content). |
| 282 | +--- |
84 | 283 |
|
85 | | -This repo is inspired from [0xbrock](https://github.com/0xbrock/FileTypeChecker) and the original code can be found in the "original" branch. I re-writed the all project with goal to make it Object oriented, with fluent API and easy to extend. |
| 284 | +<div align="center"> |
| 285 | + <strong>Made with ❤️ by <a href="https://github.com/AJMitev">Aleksandar J. Mitev</a></strong> |
| 286 | +</div> |
0 commit comments