affaan-m/ECC · warning · ValidationError

Unsupported file type.

Error message

Unsupported file type.

What it means

validate_file_type() in the django-security skill reads the first 2048 bytes, gets the MIME via python-magic, and raises django ValidationError('Unsupported file type.') if the detected MIME is not in ALLOWED_MIMES (image/jpeg, image/png, image/gif, application/pdf). This is a magic-byte allowlist: the browser-supplied extension and Content-Type are irrelevant at this stage — only the detected content type matters. libmagic must be installed (libmagic / file) or the call itself will fail before this line.

Source

Thrown at skills/django-security/SKILL.md:415

ALLOWED_MIMES = {
    'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}

MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
}

def validate_file_type(value):
    """Validate file type using magic bytes and cross-check extension."""
    mime = magic.from_buffer(value.read(2048), mime=True)
    value.seek(0)

    if mime not in ALLOWED_MIMES:
        raise ValidationError('Unsupported file type.')

    ext = os.path.splitext(value.name)[1].lower()
    if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
        raise ValidationError('File extension does not match file content.')

def validate_file_size(value):
    """Validate file size (max 5MB)."""
    if value.size > 5 * 1024 * 1024:
        raise ValidationError('File too large. Max size is 5MB.')

# models.py
class Document(models.Model):
    file = models.FileField(
        upload_to='documents/',
        validators=[validate_file_type, validate_file_size]
    )

```

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Confirm the upload is one of jpeg/png/gif/pdf; convert webp/heic before upload.
  2. Extend ALLOWED_MIMES (and add the matching extensions to MIME_TO_EXTENSIONS) if a new type is genuinely supported.
  3. Verify libmagic is installed and its database is current.
  4. Do not trust the browser Content-Type — this validator intentionally ignores it.

Example fix

// before
ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf'}

// after — add webp support
ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'image/webp'}
MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
    'image/webp': {'.webp'},
}
Defensive patterns

Strategy: validation

Validate before calling

import magic

ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf'}

def will_pass_mime(path: str) -> bool:
    with open(path, "rb") as f:
        mime = magic.from_buffer(f.read(2048), mime=True)
    return mime in ALLOWED_MIMES

Type guard

from django.core.exceptions import ValidationError

def is_unsupported_file(exc: BaseException) -> bool:
    return isinstance(exc, ValidationError) and "Unsupported file type" in str(exc)

Try / catch

from django.core.exceptions import ValidationError

try:
    validate_file_type(uploaded)
except ValidationError as e:
    if "Unsupported file type" in str(e):
        return JsonResponse({"error": "Only JPEG, PNG, GIF, PDF allowed"}, status=400)
    raise

Prevention

When it happens

Trigger: Uploading a file whose magic-byte MIME is outside the allowed set — e.g. webp, heic, svg, docx, txt, video; or a file libmagic misidentifies due to a stale magic database.

Common situations: Users uploading webp/heic screenshots (not in the allowlist); SVG logos; Office documents where only PDF is accepted; libmagic returning a non-standard MIME; libmagic not installed so from_buffer errors.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/96bebc42d3d8863f. Report an issue: GitHub.