For Laravel uploads, use mimes or mimetypes, which inspect file content, and never rely on extensions alone. The image rule is a convenient choice for pictures and excludes SVG by default because of XSS risk. Combine rules with a size limit and store files under generated names.
What each rule actually checks
The Laravel validation documentation is clear about the differences.
| Rule | What it checks | Caveat from the docs |
|---|---|---|
mimes:jpg,png | MIME type guessed by reading the file contents | Does not verify the user assigned extension agrees |
mimetypes:image/* | MIME type guessed from contents, may differ from the client's claim | You list full MIME types |
extensions:jpg,png | The user assigned extension | Never rely on it alone; combine with mimes or mimetypes |
image | File is jpg, jpeg, png, bmp, gif or webp | SVG not allowed unless you pass image:allow_svg |
dimensions | Image width, height or ratio | Only for images |
A file named photo.txt that contains valid PNG data passes mimes:png, because the rule reads content. That is correct behaviour, but it is why the docs say to add extensions when the name matters.
A sensible rule set
$request->validate([
'avatar' => [
'required',
'file',
'image',
'mimes:jpg,png,webp',
'extensions:jpg,png,webp',
'max:2048',
],
]);
The max rule is in kilobytes. Also set the PHP and web server upload limits so oversized requests are rejected before they reach your code.
Why SVG needs thought
An SVG is XML that can carry script. The docs say the image rule excludes it by default because of XSS. If you do allow it with image:allow_svg, serve it from a separate domain or with a download disposition, or sanitize it first.
Steps for a safe upload flow
- Validate type by content, size and, where useful, dimensions.
- Let Laravel generate the stored name. Methods like
putFilecreate a unique ID for the filename automatically, so a user supplied name never becomes a path. - Store uploads on a disk that is not publicly served unless the file must be public.
- For private files, serve through a controller or a temporary URL.
- Do not render user files inline from your main domain without thought.
- Scan for malware if the files are shared with other users.
On the public disk, remember that storage:link makes storage/app/public reachable from the web through public/storage. Anything you put there is downloadable by anyone with the URL.
What validation cannot do
Content sniffing reduces risk but does not prove a file is harmless. A valid image can still carry odd metadata or exploit a bug in an image library. Keep libraries patched, which is a dependency question as much as a code one.
Quick check
Is the client supplied MIME type trustworthy?
No. The docs note that the guessed type can differ from what the client sent. That is why the rules read the file.
Should I use extensions instead of mimes?
No. Use mimes or mimetypes, and add extensions as a second check.
Safeguard's dependency scanning and SBOM generation can show which image and file handling libraries your project ships. A free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.