diff --git a/src/Plugin/FitCheck/FileUploadExtensionCheck.php b/src/Plugin/FitCheck/FileUploadExtensionCheck.php
new file mode 100644
index 0000000..afd07d5
--- /dev/null
+++ b/src/Plugin/FitCheck/FileUploadExtensionCheck.php
@@ -0,0 +1,192 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\drupalfit\Plugin\FitCheck;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\field\FieldConfigInterface;
+use Drupal\drupalfit\Attribute\FitCheck;
+use Drupal\drupalfit\Enum\FitWeight;
+use Drupal\drupalfit\FitCheckPluginBase;
+use Drupal\drupalfit\FitResult;
+use Drupal\drupalfit\Plugin\FitCheckGroup\SecurityGroup;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the file upload extension check.
+ */
+#[FitCheck(
+  id: 'file_upload_extension_check',
+  fitGroup: SecurityGroup::GROUP_ID,
+  label: new TranslatableMarkup('File Upload Extensions'),
+  description: new TranslatableMarkup('Checks for dangerous or unrestricted file extensions in file/media fields.'),
+  successMessage: new TranslatableMarkup('File upload extensions are secure.'),
+  failureMessage: new TranslatableMarkup('Dangerous file extensions detected.'),
+)]
+class FileUploadExtensionCheck extends FitCheckPluginBase {
+
+  /**
+   * {@inheritDoc}
+   */
+  public function __construct(
+    array $configuration,
+    string $plugin_id,
+    mixed $plugin_definition,
+    protected readonly EntityTypeManagerInterface $entityTypeManager,
+  ) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * Inject the required services.
+   */
+  public static function create(
+    ContainerInterface $container,
+    array $configuration,
+    $plugin_id,
+    mixed $plugin_definition,
+  ): static {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public function execute(): FitResult {
+    $result = FitResult::create(
+      $this->getPluginId(),
+      $this->label(),
+      $this->fitGroup(),
+      FitWeight::Ok
+    );
+
+    $dangerous_fields = $this->findDangerousFileFields();
+
+    if (!empty($dangerous_fields)) {
+      $issues = [];
+      foreach ($dangerous_fields as $field_info) {
+        $issues[] = $this->t('@entity_type.@bundle.@field_name: @extensions', [
+          '@entity_type' => $field_info['entity_type'],
+          '@bundle' => $field_info['bundle'],
+          '@field_name' => $field_info['field_name'],
+          '@extensions' => $field_info['extensions'],
+        ]);
+      }
+
+      $result
+        ->setWeight(FitWeight::High)
+        ->setFailureMessage($this->failureMessage())
+        ->setHelpMessage([
+          '#type' => 'inline_template',
+          '#template' => '<strong>{{ label }}</strong><br>{{ items|raw }}<br><br>{{ fix }}<br><a href="{{ url }}" target="_blank">{{ link }}</a>',
+          '#context' => [
+            'label' => $this->t('Fields with dangerous extensions:'),
+            'items' => implode('<br>', $issues),
+            'fix' => $this->t('Review and restrict file extensions to safe types only (e.g., jpg, png, pdf, doc).'),
+            'url' => 'https://www.drupal.org/docs/administering-a-drupal-site/security-in-drupal/securing-file-permissions-and-ownership',
+            'link' => $this->t('Learn more about file upload security'),
+          ],
+        ]);
+    }
+    else {
+      $result->setSuccessMessage($this->successMessage());
+    }
+
+    return $result;
+  }
+
+  /**
+   * Finds file/media fields with dangerous or unrestricted extensions.
+   *
+   * @return array
+   *   Array of field information with dangerous extensions.
+   */
+  private function findDangerousFileFields(): array {
+    $dangerous_fields = [];
+    $dangerous_extensions = $this->getDangerousExtensions();
+
+    // Get all field configs for file and image fields
+    $field_configs = $this->entityTypeManager
+      ->getStorage('field_config')
+      ->loadMultiple();
+
+    foreach ($field_configs as $field_config) {
+      /** @var \Drupal\field\FieldConfigInterface $field_config */
+      $field_type = $field_config->getType();
+      
+      // Check file, image, and media reference fields
+      if (!in_array($field_type, ['file', 'image', 'entity_reference'], TRUE)) {
+        continue;
+      }
+
+      // For entity_reference fields, check if they reference media
+      if ($field_type === 'entity_reference') {
+        $settings = $field_config->getSettings();
+        if (empty($settings['target_type']) || $settings['target_type'] !== 'media') {
+          continue;
+        }
+      }
+
+      $settings = $field_config->getSettings();
+      $file_extensions = $settings['file_extensions'] ?? '';
+
+      // Empty extensions means all extensions are allowed - very dangerous
+      if (empty($file_extensions)) {
+        $dangerous_fields[] = [
+          'entity_type' => $field_config->getTargetEntityTypeId(),
+          'bundle' => $field_config->getTargetBundle(),
+          'field_name' => $field_config->getName(),
+          'extensions' => $this->t('ALL EXTENSIONS ALLOWED'),
+          'severity' => 'critical',
+        ];
+        continue;
+      }
+
+      // Check for dangerous extensions
+      $allowed_extensions = array_map('trim', explode(' ', $file_extensions));
+      $found_dangerous = array_intersect($allowed_extensions, $dangerous_extensions);
+
+      if (!empty($found_dangerous)) {
+        $dangerous_fields[] = [
+          'entity_type' => $field_config->getTargetEntityTypeId(),
+          'bundle' => $field_config->getTargetBundle(),
+          'field_name' => $field_config->getName(),
+          'extensions' => implode(', ', $found_dangerous),
+          'severity' => 'high',
+        ];
+      }
+    }
+
+    return $dangerous_fields;
+  }
+
+  /**
+   * Gets list of dangerous file extensions.
+   *
+   * @return string[]
+   *   Array of dangerous file extensions.
+   */
+  private function getDangerousExtensions(): array {
+    return [
+      // Executable files
+      'exe', 'com', 'bat', 'cmd', 'scr', 'pif', 'msi', 'app', 'deb', 'rpm',
+      // Script files
+      'php', 'php3', 'php4', 'php5', 'phtml', 'asp', 'aspx', 'jsp', 'pl', 'py', 'rb', 'cgi',
+      'sh', 'bash', 'zsh', 'fish', 'ps1', 'vbs', 'js', 'jar',
+      // Configuration and system files
+      'htaccess', 'htpasswd', 'ini', 'conf', 'config', 'cfg',
+      // Archive files that could contain executables
+      'zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz',
+      // Other potentially dangerous
+      'sql', 'db', 'sqlite', 'mdb',
+    ];
+  }
+
+}
\ No newline at end of file
diff --git a/src/Plugin/FitCheck/FileUploadSchemeCheck.php b/src/Plugin/FitCheck/FileUploadSchemeCheck.php
new file mode 100644
index 0000000..da1fc16
--- /dev/null
+++ b/src/Plugin/FitCheck/FileUploadSchemeCheck.php
@@ -0,0 +1,221 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\drupalfit\Plugin\FitCheck;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\field\FieldConfigInterface;
+use Drupal\drupalfit\Attribute\FitCheck;
+use Drupal\drupalfit\Enum\FitWeight;
+use Drupal\drupalfit\FitCheckPluginBase;
+use Drupal\drupalfit\FitResult;
+use Drupal\drupalfit\Plugin\FitCheckGroup\SecurityGroup;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the file upload scheme check.
+ */
+#[FitCheck(
+  id: 'file_upload_scheme_check',
+  fitGroup: SecurityGroup::GROUP_ID,
+  label: new TranslatableMarkup('File Upload Storage Scheme'),
+  description: new TranslatableMarkup('Verifies that uploaded files are stored on non-executable schemes/paths.'),
+  successMessage: new TranslatableMarkup('File upload storage schemes are secure.'),
+  failureMessage: new TranslatableMarkup('Insecure file storage schemes detected.'),
+)]
+class FileUploadSchemeCheck extends FitCheckPluginBase {
+
+  /**
+   * {@inheritDoc}
+   */
+  public function __construct(
+    array $configuration,
+    string $plugin_id,
+    mixed $plugin_definition,
+    protected readonly EntityTypeManagerInterface $entityTypeManager,
+    protected readonly StreamWrapperManagerInterface $streamWrapperManager,
+  ) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * Inject the required services.
+   */
+  public static function create(
+    ContainerInterface $container,
+    array $configuration,
+    $plugin_id,
+    mixed $plugin_definition,
+  ): static {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager'),
+      $container->get('stream_wrapper_manager')
+    );
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public function execute(): FitResult {
+    $result = FitResult::create(
+      $this->getPluginId(),
+      $this->label(),
+      $this->fitGroup(),
+      FitWeight::Ok
+    );
+
+    $insecure_fields = $this->findInsecureFileFields();
+
+    if (!empty($insecure_fields)) {
+      $issues = [];
+      foreach ($insecure_fields as $field_info) {
+        $issues[] = $this->t('@entity_type.@bundle.@field_name: @scheme (@directory)', [
+          '@entity_type' => $field_info['entity_type'],
+          '@bundle' => $field_info['bundle'],
+          '@field_name' => $field_info['field_name'],
+          '@scheme' => $field_info['scheme'],
+          '@directory' => $field_info['directory'],
+        ]);
+      }
+
+      $result
+        ->setWeight(FitWeight::Medium)
+        ->setFailureMessage($this->failureMessage())
+        ->setHelpMessage([
+          '#type' => 'inline_template',
+          '#template' => '<strong>{{ label }}</strong><br>{{ items|raw }}<br><br>{{ fix }}<br><a href="{{ url }}" target="_blank">{{ link }}</a>',
+          '#context' => [
+            'label' => $this->t('Fields with insecure storage:'),
+            'items' => implode('<br>', $issues),
+            'fix' => $this->t('Consider using private:// scheme or ensure public directories are not executable.'),
+            'url' => 'https://www.drupal.org/docs/administering-a-drupal-site/security-in-drupal/securing-file-permissions-and-ownership',
+            'link' => $this->t('Learn more about secure file storage'),
+          ],
+        ]);
+    }
+    else {
+      $result->setSuccessMessage($this->successMessage());
+    }
+
+    return $result;
+  }
+
+  /**
+   * Finds file/media fields with insecure storage schemes.
+   *
+   * @return array
+   *   Array of field information with insecure storage.
+   */
+  private function findInsecureFileFields(): array {
+    $insecure_fields = [];
+
+    // Get all field configs for file and image fields
+    $field_configs = $this->entityTypeManager
+      ->getStorage('field_config')
+      ->loadMultiple();
+
+    foreach ($field_configs as $field_config) {
+      /** @var \Drupal\field\FieldConfigInterface $field_config */
+      $field_type = $field_config->getType();
+      
+      // Check file, image, and media reference fields
+      if (!in_array($field_type, ['file', 'image', 'entity_reference'], TRUE)) {
+        continue;
+      }
+
+      // For entity_reference fields, check if they reference media
+      if ($field_type === 'entity_reference') {
+        $settings = $field_config->getSettings();
+        if (empty($settings['target_type']) || $settings['target_type'] !== 'media') {
+          continue;
+        }
+      }
+
+      $settings = $field_config->getSettings();
+      $uri_scheme = $settings['uri_scheme'] ?? 'public';
+      $file_directory = $settings['file_directory'] ?? '';
+
+      // Check if the scheme is potentially insecure
+      if ($this->isInsecureScheme($uri_scheme, $file_directory)) {
+        $insecure_fields[] = [
+          'entity_type' => $field_config->getTargetEntityTypeId(),
+          'bundle' => $field_config->getTargetBundle(),
+          'field_name' => $field_config->getName(),
+          'scheme' => $uri_scheme,
+          'directory' => $file_directory,
+        ];
+      }
+    }
+
+    return $insecure_fields;
+  }
+
+  /**
+   * Determines if a URI scheme and directory combination is insecure.
+   *
+   * @param string $scheme
+   *   The URI scheme (e.g., 'public', 'private').
+   * @param string $directory
+   *   The file directory within the scheme.
+   *
+   * @return bool
+   *   TRUE if the scheme/directory is considered insecure.
+   */
+  private function isInsecureScheme(string $scheme, string $directory): bool {
+    // Private scheme is generally secure
+    if ($scheme === 'private') {
+      return FALSE;
+    }
+
+    // Public scheme can be insecure, especially with certain directories
+    if ($scheme === 'public') {
+      // Check for potentially dangerous directories
+      $dangerous_directories = [
+        'scripts',
+        'js',
+        'css',
+        'php',
+        'cgi-bin',
+        'bin',
+        'admin',
+        'config',
+        'includes',
+        'modules',
+        'themes',
+        'core',
+      ];
+
+      $directory_lower = strtolower($directory);
+      foreach ($dangerous_directories as $dangerous_dir) {
+        if (strpos($directory_lower, $dangerous_dir) !== FALSE) {
+          return TRUE;
+        }
+      }
+
+      // Files in the root of public:// can be more risky
+      if (empty($directory)) {
+        return TRUE;
+      }
+
+      // Public scheme with safe subdirectory is generally OK
+      return FALSE;
+    }
+
+    // For other schemes, check if they're known to Drupal
+    $wrappers = $this->streamWrapperManager->getWrappers();
+    if (!isset($wrappers[$scheme])) {
+      // Unknown schemes might be problematic
+      return TRUE;
+    }
+
+    // Known schemes that aren't public or private are generally OK
+    return FALSE;
+  }
+
+}
\ No newline at end of file
