diff --git a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceTest.php b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceTest.php
index 68695641a0..9658e33d57 100644
--- a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceTest.php
+++ b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceTest.php
@@ -79,6 +79,7 @@ public function testFieldInstanceMigration() {
       'file_extensions' => 'txt pdf doc',
       'file_directory' => 'images',
       'description_field' => TRUE,
+      'description_field_required' => FALSE,
       'max_filesize' => '200KB',
       'target_type' => 'file',
       'display_field' => FALSE,
diff --git a/core/modules/file/config/schema/file.schema.yml b/core/modules/file/config/schema/file.schema.yml
index b9f8918f63..f1e4cc53b7 100644
--- a/core/modules/file/config/schema/file.schema.yml
+++ b/core/modules/file/config/schema/file.schema.yml
@@ -58,6 +58,9 @@ base_file_field_field_settings:
     max_filesize:
       type: string
       label: 'Maximum upload size'
+    description_field_required:
+      type: boolean
+      label: 'Require Description field'
 
 field.field_settings.file:
   type: base_file_field_field_settings
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
index 7373c4397f..aa458896f4 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
@@ -49,6 +49,7 @@ public static function defaultFieldSettings() {
       'file_directory' => '[date:custom:Y]-[date:custom:m]',
       'max_filesize' => '',
       'description_field' => 0,
+      'description_field_required' => FALSE,
     ] + parent::defaultFieldSettings();
   }
 
@@ -191,6 +192,19 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#weight' => 11,
     ];
 
+    $element['description_field_required'] = [
+      '#type' => 'checkbox',
+      '#title' => t('Require the <em>Description</em> field'),
+      '#default_value' => isset($settings['description_field_required']) ? $settings['description_field_required'] : '',
+      '#description' => t('Whether or not the description field is required.'),
+      '#weight' => 12,
+      '#states' => [
+        'visible' => [
+          ':input[name="settings[description_field]"]' => ['checked' => TRUE],
+        ],
+      ],
+    ];
+
     return $element;
   }
 
diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
index 587a396fc6..744ff9643f 100644
--- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -214,6 +214,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       'display_default' => NULL,
       'display_field' => NULL,
       'description_field' => NULL,
+      'description_field_required' => NULL,
     ];
 
     $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
@@ -241,6 +242,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       '#display_field' => (bool) $field_settings['display_field'],
       '#display_default' => $field_settings['display_default'],
       '#description_field' => $field_settings['description_field'],
+      '#description_field_required' => $field_settings['description_field_required'],
       '#cardinality' => $cardinality,
     ];
 
@@ -267,6 +269,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
         $element['#element_validate'] = [[get_class($this), 'validateMultipleCount']];
       }
     }
+    if (!empty($element['#description_field_required'])) {
+      $element['#element_validate'][] = [get_class($this), 'validateRequiredDescription'];
+    }
 
     return $element;
   }
@@ -334,6 +339,33 @@ public static function value($element, $input, FormStateInterface $form_state) {
   }
 
   /**
+   * #element_validate callback to check if a required description is filled in.
+   *
+   * @param array $element
+   *   An associative array containing the properties and children of the
+   *   generic form element.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   * @param array $complete_form
+   *   The complete form structure.
+   */
+  public static function validateRequiredDescription(array &$element, FormStateInterface $form_state, array &$complete_form) {
+    // Skip validation if a file is being uploaded or deleted.
+    $parent = array_slice($element['#parents'], 0, -1);
+    $trigger_parents = $form_state->getTriggeringElement()['#parents'];
+    if (array_diff($parent, array_intersect($parent, $trigger_parents)) === []) {
+      if (in_array(array_pop($trigger_parents), ['upload_button', 'remove_button'])) {
+        return;
+      }
+    }
+    // Throw a validation error if a file is present but the description is
+    // empty.
+    if (!empty($element['fids']['#value']) && empty($element['description']['#value'])) {
+      $form_state->setError($element, t('@name field is required.', ['@name' => $element['description']['#title']]));
+    }
+  }
+
+  /**
    * Form element validation callback for upload element on file widget. Checks
    * if user has uploaded more files than allowed.
    *
@@ -413,6 +445,7 @@ public static function process($element, FormStateInterface $form_state, $form)
         '#value' => isset($item['description']) ? $item['description'] : '',
         '#maxlength' => $config->get('description.length'),
         '#description' => t('The description may be used as the label of the link to the file.'),
+        '#required' => !empty($element['#description_field_required']),
       ];
     }
 
diff --git a/core/modules/file/src/Tests/FileFieldDisplayTest.php b/core/modules/file/src/Tests/FileFieldDisplayTest.php
index 1b7e534211..d318699c94 100644
--- a/core/modules/file/src/Tests/FileFieldDisplayTest.php
+++ b/core/modules/file/src/Tests/FileFieldDisplayTest.php
@@ -171,6 +171,16 @@ public function testDescToggle() {
     $node = $this->drupalGetNodeByTitle($title);
     $this->drupalGet('node/' . $node->id() . '/edit');
     $this->assertText(t('The description may be used as the label of the link to the file.'));
+
+    // Set the description field as required.
+    $edit = ['settings[description_field_required]' => TRUE];
+    $this->drupalGet('admin/structure/types/manage/' . $type_name . '/fields');
+    $this->drupalPostForm('admin/structure/types/manage/' . $type_name . '/fields/node.' . $type_name . '.field_' . $field_name, $edit, t('Save settings'));
+    // When resubmitting the form a message should be shown indicating that the
+    // description is now required.
+    $this->drupalGet('node/' . $node->id() . '/edit');
+    $this->drupalPostForm(NULL, [], t('Save and keep published'));
+    $this->assertText(t('Description field is required.'));
   }
 
 }
diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
index 7b8b275216..97255cfb7d 100644
--- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
@@ -88,6 +88,7 @@ public static function defaultFieldSettings() {
     ] + parent::defaultFieldSettings();
 
     unset($settings['description_field']);
+    unset($settings['description_field_required']);
     return $settings;
   }
 
