diff --git a/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
index 6664b2d3ec7ee81aa760bb00423d2e39f81d1c17..246f143d4e25d0e9bc6b732b8253e7ced2ff351c 100644
--- a/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
+++ b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
@@ -123,6 +123,7 @@ public function validateDefinition(array $definition, bool $enforce_schemas): bo
     );
 
     $definition_object = Validator::arrayToObjectRecursive($definition);
+    $this->validator->reset();
     $this->validator->validate(
       $definition_object,
       (object) ['$ref' => 'file://' . dirname(__DIR__, 5) . '/assets/schemas/v1/metadata-full.schema.json']
@@ -188,15 +189,15 @@ public function validateProps(array $context, Component $component): bool {
     ] = $this->validateClassProps($schema, $props_raw, $component_id);
     $schema = Validator::arrayToObjectRecursive($schema);
     $props = Validator::arrayToObjectRecursive($props_raw);
-    $validator = new Validator();
-    $validator->validate($props, $schema, Constraint::CHECK_MODE_TYPE_CAST);
-    $validator->getErrors();
-    if ($validator->isValid()) {
+    $this->validator->reset();
+    $this->validator->validate($props, $schema, Constraint::CHECK_MODE_TYPE_CAST);
+    $this->validator->getErrors();
+    if ($this->validator->isValid()) {
       return TRUE;
     }
     // Dismiss type errors if the prop received a render array.
     $errors = array_filter(
-      $validator->getErrors(),
+      $this->validator->getErrors(),
       function (array $error) use ($context): bool {
         if (($error['constraint'] ?? '') !== 'type') {
           return TRUE;
diff --git a/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
index ff79612b494e20dbbff7b70f603532fec903ce23..df03332cf4b1918b84e06b81b32ed2a8d05f99d2 100644
--- a/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
@@ -4,10 +4,15 @@
 
 namespace Drupal\Tests\Core\Theme\Component;
 
+use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Theme\Component\ComponentValidator;
 use Drupal\Core\Render\Component\Exception\InvalidComponentException;
 use Drupal\Core\Plugin\Component;
+use JsonSchema\Constraints\Factory;
+use JsonSchema\Constraints\FormatConstraint;
+use JsonSchema\Entity\JsonPointer;
+use JsonSchema\Validator;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Yaml\Yaml;
 
@@ -168,6 +173,33 @@ public static function dataProviderValidatePropsValid(): array {
     ];
   }
 
+  /**
+   * Tests we can use a custom validator to validate props.
+   */
+  public function testCustomValidator(): void {
+    $component = new Component(
+      ['app_root' => '/fake/path/root'],
+      'sdc_test:my-cta',
+      static::loadComponentDefinitionFromFs('my-cta'),
+    );
+    $component_validator = new ComponentValidator();
+    // A validator with a constraint factory that uses a custom constraint for
+    // checking format.
+    $component_validator->setValidator(new Validator((new Factory())->setConstraintClass('format', UrlHelperFormatConstraint::class)));
+    self::assertTrue(
+      $component_validator->validateProps([
+        'text' => 'Can Pica',
+        // This is a valid URI but for v5.2 of justinrainbow/json-schema it
+        // does not pass validation without a custom constraint for format.
+        // We pass a custom factory and it should be used.
+        'href' => 'entity:node/1',
+        'target' => '_blank',
+        'attributes' => new Attribute(['key' => 'value']),
+      ], $component),
+      'The valid component props threw an error.'
+    );
+  }
+
   /**
    * Tests that invalid props are handled properly.
    *
@@ -255,3 +287,26 @@ private static function loadComponentDefinitionFromFs(string $component_name): a
   }
 
 }
+
+/**
+ * Defines a custom format constraint for json-schema.
+ */
+class UrlHelperFormatConstraint extends FormatConstraint {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function check(&$element, $schema = NULL, ?JsonPointer $path = NULL, $i = NULL): void {
+    if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
+      return;
+    }
+    if ($schema->format === 'uri') {
+      if (\is_string($element) && !UrlHelper::isValid($element)) {
+        $this->addError($path, 'Invalid URL format', 'format', ['format' => $schema->format]);
+      }
+      return;
+    }
+    parent::check($element, $schema, $path, $i);
+  }
+
+}