yousefkadah / laravel-magika
Laravel package for AI-powered file type validation using Google's Magika model
Requires
- php: ^8.1
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- illuminate/validation: ^10.0|^11.0|^12.0|^13.0
- symfony/process: ^6.0|^7.0|^8.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0
README
AI-powered file type validation for Laravel using Google's Magika — a deep learning model (~1 MB) that achieves ~99% accuracy across 200+ content types.
Unlike traditional MIME-type checking (which relies on file extensions or magic bytes), Magika uses a trained neural network to accurately identify file content, making it significantly harder to bypass with spoofed extensions or headers.
Requirements
- PHP 8.1+
- Laravel 10, 11, or 12
- Magika CLI installed on your system
Installing the Magika CLI
Choose one:
# macOS / Linux (Homebrew) brew install magika # Python (pipx) pipx install magika # Rust (Cargo) cargo install --locked magika-cli
Installation
composer require yousefkadah/laravel-magika
Publish the configuration (optional):
php artisan vendor:publish --tag=magika-config
Configuration
// config/magika.php return [ 'binary_path' => env('MAGIKA_BINARY_PATH', null), // null = use system PATH 'prediction_mode' => env('MAGIKA_PREDICTION_MODE', 'high-confidence'), 'timeout' => env('MAGIKA_TIMEOUT', 30), ];
Usage
Detecting File Types
use YousefKadah\LaravelMagika\Facades\Magika; // Detect a file by path $result = Magika::detect('/path/to/file.pdf'); $result->label; // "pdf" $result->mimeType; // "application/pdf" $result->group; // "document" $result->description; // "PDF document" $result->score; // 0.99 $result->isText; // false $result->extensions; // ["pdf"] // Detect from raw content $result = Magika::detectContent('<?php echo "hello";'); $result->label; // "php" // Detect an uploaded file $result = Magika::detectUploadedFile($request->file('document')); // Batch detection $results = Magika::detectMany(['/path/to/file1.pdf', '/path/to/file2.jpg']);
Validation Rules
By Magika Label
Validate that an uploaded file matches specific Magika content type labels:
// Using string rule (in controller or form request) $request->validate([ 'document' => 'required|file|magika:pdf,docx,xlsx', ]); // Using invokable rule use YousefKadah\LaravelMagika\Rules\MagikaFileType; $request->validate([ 'document' => ['required', 'file', new MagikaFileType(['pdf', 'docx', 'xlsx'])], ]);
By MIME Type
// Using string rule $request->validate([ 'image' => 'required|file|magika_mime:image/png,image/jpeg', ]); // Using invokable rule use YousefKadah\LaravelMagika\Rules\MagikaMimeType; $request->validate([ 'image' => ['required', 'file', new MagikaMimeType(['image/png', 'image/jpeg'])], ]);
By Group
// Using string rule $request->validate([ 'upload' => 'required|file|magika_group:document,image', ]); // Using invokable rule use YousefKadah\LaravelMagika\Rules\MagikaGroup; $request->validate([ 'upload' => ['required', 'file', new MagikaGroup(['document', 'image'])], ]);
Checking Installation
use YousefKadah\LaravelMagika\Facades\Magika; Magika::isInstalled(); // true/false Magika::version(); // "magika 0.1.0-rc.3 (model standard_v3_3)"
MagikaResult API
| Property | Type | Description |
|---|---|---|
path |
string | File path that was analyzed |
label |
string | Content type label (e.g. pdf, python) |
mimeType |
string | MIME type (e.g. application/pdf) |
group |
string | Group category (e.g. document, code) |
description |
string | Human-readable description |
score |
float | Confidence score (0.0 - 1.0) |
isText |
bool | Whether the content is text-based |
extensions |
array | Possible file extensions |
status |
string | Detection status (ok or error) |
| Method | Returns | Description |
|---|---|---|
isOk() |
bool | Whether detection succeeded |
matchesLabel(string|array) |
bool | Check against label(s) |
matchesMimeType(string|array) |
bool | Check against MIME type(s) |
matchesGroup(string|array) |
bool | Check against group(s) |
Common Magika Labels
| Label | MIME Type | Group |
|---|---|---|
pdf |
application/pdf |
document |
png |
image/png |
image |
jpeg |
image/jpeg |
image |
gif |
image/gif |
image |
docx |
application/vnd.openxmlformats-officedocument.wordprocessingml.document |
document |
xlsx |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
document |
zip |
application/zip |
archive |
python |
text/x-python |
code |
javascript |
text/javascript |
code |
html |
text/html |
code |
csv |
text/csv |
code |
json |
application/json |
code |
xml |
text/xml |
code |
mp3 |
audio/mpeg |
audio |
mp4 |
video/mp4 |
video |
For the full list of 200+ supported types, see the Magika content types documentation.
Why Use Magika Over Standard Validation?
Laravel's built-in mimes and mimetypes rules rely on file extensions and PHP's finfo (which uses libmagic). These can be easily tricked:
- Renaming
malware.exetomalware.pdfbypasses extension checks - Crafted files can fool magic-byte detection
Magika uses a deep learning model trained on ~100M files, analyzing actual file content patterns — making it far more robust against evasion.
License
MIT License. See LICENSE for details.