octobercms/october · error · ApplicationException

backend::lang.media.type_blocked

Error message

backend::lang.media.type_blocked

What it means

MediaLibrary::validateExtension() enforces the extension allow-list from FileDefinitions::get('default_extensions') on every write into the media library. A path whose (lowercased) extension is not in that list — .php, .html, .psd, .heic, or a file with no extension at all — throws backend::lang.media.type_blocked. The docblock is explicit: all write entry points funnel through here so nothing with an arbitrary extension lands in the public media folder.

Source

Thrown at modules/media/classes/MediaLibrary.php:542

            throw new ApplicationException(Lang::get('system::lang.media.invalid_path', compact('path')));
        }

        return $path;
    }

    /**
     * validateExtension enforces the Media Library extension allow-list on a destination
     * path. Every write entry point should pass through here so callers cannot drop a file
     * with an arbitrary extension into the public media folder.
     */
    public static function validateExtension(string $path): void
    {
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));

        $allowedFileTypes = FileDefinitions::get('default_extensions');

        if (!in_array($extension, $allowedFileTypes)) {
            throw new ApplicationException(Lang::get('backend::lang.media.type_blocked'));
        }

        if (System::checkSafeMode() && in_array($extension, ['less', 'sass', 'scss'])) {
            throw new ApplicationException(Lang::get('backend::lang.media.type_blocked'));
        }
    }

    /**
     * url is a helper that makes a URL for a media file.
     * Ideally the file should be passed as a string but it will try to deal with anything.
     * @param string $file
     * @return string
     */
    public static function url($file)
    {
        if (is_array($file)) {
            $file = array_first($file);
        }

View on GitHub (pinned to b608633a7e)

Solutions

  1. Upload/rename to a whitelisted extension — inspect FileDefinitions::get('default_extensions') to see the live list
  2. Extend the allow-list in the file definitions config if the format is genuinely needed
  3. Convert assets (avif→jpg/png) or bundle unsupported types as zip if policy forbids the extension
  4. For custom media writes, call MediaLibrary::validateExtension($path) yourself before writing so the rejection is intentional, not a 500

Example fix

// config/filedefinitions.php — before
'default_extensions' => ['jpg','jpeg','png','gif','svg','webp'],

// after — add the formats your users actually need
'default_extensions' => ['jpg','jpeg','png','gif','svg','webp','avif','heic'],
Defensive patterns

Strategy: validation

Validate before calling

$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (!in_array($ext, FileDefinitions::get('default_extensions'), true)) {
    // reject before the write; the server list is authoritative
    return Response::json(['error' => 'Extension not permitted: '.$ext], 422);
}

Try / catch

try {
    MediaLibrary::validateExtension($destPath);
} catch (ApplicationException $e) {
    // handle policy rejection without attempting the write
    Log::notice('Blocked media write: '.$destPath);
    throw $e;
}

Prevention

When it happens

Trigger: Uploading or renaming to an extension outside default_extensions; requests attempting to drop a .php/.phtml file into the public media folder; newer formats (avif, heic) absent from the active definitions; extensionless target names.

Common situations: Users uploading modern image formats the site's definitions predate; attackers probing for executable uploads; custom file_definitions config that trimmed the list; plugin code calling putFile/write without checking the list first.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/3a98ee2c31dc43bf. Report an issue: GitHub.