Safeguard
Security Guides•

Laravel upload validation: mimes, extensions or image rule?

Use mimes or mimetypes to check Laravel upload content, add extensions only as an extra, and know that the image rule blocks SVG by default. Rules compared.

Safeguard Security Team
3 min read

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.

RuleWhat it checksCaveat from the docs
mimes:jpg,pngMIME type guessed by reading the file contentsDoes not verify the user assigned extension agrees
mimetypes:image/*MIME type guessed from contents, may differ from the client's claimYou list full MIME types
extensions:jpg,pngThe user assigned extensionNever rely on it alone; combine with mimes or mimetypes
imageFile is jpg, jpeg, png, bmp, gif or webpSVG not allowed unless you pass image:allow_svg
dimensionsImage width, height or ratioOnly 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

  1. Validate type by content, size and, where useful, dimensions.
  2. Let Laravel generate the stored name. Methods like putFile create a unique ID for the filename automatically, so a user supplied name never becomes a path.
  3. Store uploads on a disk that is not publicly served unless the file must be public.
  4. For private files, serve through a controller or a temporary URL.
  5. Do not render user files inline from your main domain without thought.
  6. 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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.