diff --git a/packages/block-editor/src/components/rich-text/use-paste-handler.js b/packages/block-editor/src/components/rich-text/use-paste-handler.js
index 5f3b93a0ecc0e9..75a58bffd9aee1 100644
--- a/packages/block-editor/src/components/rich-text/use-paste-handler.js
+++ b/packages/block-editor/src/components/rich-text/use-paste-handler.js
@@ -139,10 +139,14 @@ export function usePasteHandler( props ) {
let mode = onReplace && onSplit ? 'AUTO' : 'INLINE';
+ const trimmedPlainText = plainText.trim();
+
if (
__unstableEmbedURLOnPaste &&
isEmpty( value ) &&
- isURL( plainText.trim() )
+ isURL( trimmedPlainText ) &&
+ // For the link pasting feature, allow only http(s) protocols.
+ /^https?:/.test( trimmedPlainText )
) {
mode = 'BLOCKS';
}
diff --git a/packages/format-library/src/link/index.js b/packages/format-library/src/link/index.js
index 1596da055cc402..9faa90628e3c3b 100644
--- a/packages/format-library/src/link/index.js
+++ b/packages/format-library/src/link/index.js
@@ -144,7 +144,8 @@ export const link = {
.trim();
// A URL was pasted, turn the selection into a link.
- if ( ! isURL( pastedText ) ) {
+ // For the link pasting feature, allow only http(s) protocols.
+ if ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {
return value;
}
diff --git a/test/e2e/specs/editor/various/copy-cut-paste.spec.js b/test/e2e/specs/editor/various/copy-cut-paste.spec.js
index 4c249349243669..2a2fd95636e7fa 100644
--- a/test/e2e/specs/editor/various/copy-cut-paste.spec.js
+++ b/test/e2e/specs/editor/various/copy-cut-paste.spec.js
@@ -496,4 +496,53 @@ test.describe( 'Copy/cut/paste', () => {
await page.keyboard.type( 'y' );
expect( await editor.getEditedPostContent() ).toMatchSnapshot();
} );
+
+ test( 'should link selection', async ( { pageUtils, editor } ) => {
+ await editor.insertBlock( {
+ name: 'core/paragraph',
+ attributes: {
+ content: 'a',
+ },
+ } );
+ await pageUtils.pressKeys( 'primary+a' );
+ pageUtils.setClipboardData( {
+ plainText: 'https://wordpress.org/gutenberg',
+ html: 'https://wordpress.org/gutenberg',
+ } );
+ await pageUtils.pressKeys( 'primary+v' );
+ expect( await editor.getBlocks() ).toMatchObject( [
+ {
+ name: 'core/paragraph',
+ attributes: {
+ content: 'a',
+ },
+ },
+ ] );
+ } );
+
+ test( 'should not link selection for non http(s) protocol', async ( {
+ pageUtils,
+ editor,
+ } ) => {
+ await editor.insertBlock( {
+ name: 'core/paragraph',
+ attributes: {
+ content: 'a',
+ },
+ } );
+ await pageUtils.pressKeys( 'primary+a' );
+ pageUtils.setClipboardData( {
+ plainText: 'movie: b',
+ html: 'movie: b',
+ } );
+ await pageUtils.pressKeys( 'primary+v' );
+ expect( await editor.getBlocks() ).toMatchObject( [
+ {
+ name: 'core/paragraph',
+ attributes: {
+ content: 'movie: b',
+ },
+ },
+ ] );
+ } );
} );