diff --git a/frontend/src/metabase/admin/datamodel/components/database/MetadataSchemaList.jsx b/frontend/src/metabase/admin/datamodel/components/database/MetadataSchemaList.jsx
index ad82e59f760315c10b1fed096695a0ba98175e2f..3b64300ac9a96d35a1686a6c14af47a4b9cbe54d 100644
--- a/frontend/src/metabase/admin/datamodel/components/database/MetadataSchemaList.jsx
+++ b/frontend/src/metabase/admin/datamodel/components/database/MetadataSchemaList.jsx
@@ -6,6 +6,8 @@ import { t, ngettext, msgid } from "ttag";
 import _ from "underscore";
 import cx from "classnames";
 
+import { regexpEscape } from "metabase/lib/string";
+
 export default class MetadataSchemaList extends Component {
   constructor(props, context) {
     super(props, context);
@@ -22,7 +24,7 @@ export default class MetadataSchemaList extends Component {
     this.setState({
       searchText: event.target.value,
       searchRegex: event.target.value
-        ? new RegExp(RegExp.escape(event.target.value), "i")
+        ? new RegExp(regexpEscape(event.target.value), "i")
         : null,
     });
   }
diff --git a/frontend/src/metabase/admin/datamodel/components/database/MetadataTableList.jsx b/frontend/src/metabase/admin/datamodel/components/database/MetadataTableList.jsx
index cf425503e003ac6be04f57a2c88f6a7a841ea221..0406cf430971dbf1e4720a3611cdfa243df8b164 100644
--- a/frontend/src/metabase/admin/datamodel/components/database/MetadataTableList.jsx
+++ b/frontend/src/metabase/admin/datamodel/components/database/MetadataTableList.jsx
@@ -8,6 +8,8 @@ import { t, ngettext, msgid } from "ttag";
 import _ from "underscore";
 import cx from "classnames";
 
+import { regexpEscape } from "metabase/lib/string";
+
 export default class MetadataTableList extends Component {
   constructor(props, context) {
     super(props, context);
@@ -30,7 +32,7 @@ export default class MetadataTableList extends Component {
     this.setState({
       searchText: event.target.value,
       searchRegex: event.target.value
-        ? new RegExp(RegExp.escape(event.target.value), "i")
+        ? new RegExp(regexpEscape(event.target.value), "i")
         : null,
     });
   }
diff --git a/frontend/src/metabase/lib/string.js b/frontend/src/metabase/lib/string.js
index 8fb1e7a7af791f04675c0a026a5b0a78b015f3d8..d6b6fe78fe3fd03e1830f9fe585626b01613ed38 100644
--- a/frontend/src/metabase/lib/string.js
+++ b/frontend/src/metabase/lib/string.js
@@ -3,15 +3,17 @@ import _ from "underscore";
 // Creates a regex that will find an order dependent, case insensitive substring. All whitespace will be rendered as ".*" in the regex, to create a fuzzy search.
 export function createMultiwordSearchRegex(input) {
   if (input) {
-    return new RegExp(
-      _.map(input.split(/\s+/), word => {
-        return RegExp.escape(word);
-      }).join(".*"),
-      "i",
-    );
+    return new RegExp(_.map(input.split(/\s+/), regexpEscape).join(".*"), "i");
   }
 }
 
+// prefix special characters with "\" for creating a regex
+export function regexpEscape(s) {
+  const regexpSpecialChars = /[\^\$\\\.\*\+\?\(\)\[\]\{\}\|]/g;
+  // "$&" in the replacement string is replaced with the matched string
+  return s.replace(regexpSpecialChars, "\\$&");
+}
+
 export const countLines = str => str.split(/\n/g).length;
 
 export function caseInsensitiveSearch(haystack, needle) {
diff --git a/frontend/test/metabase/lib/string.unit.spec.js b/frontend/test/metabase/lib/string.unit.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..6632e327d42434ef1455ff60ea2605e4e6b3bc98
--- /dev/null
+++ b/frontend/test/metabase/lib/string.unit.spec.js
@@ -0,0 +1,17 @@
+import { regexpEscape } from "metabase/lib/string";
+
+describe("regexpEscape", () => {
+  const testCases = [
+    ["nothing special here", "nothing special here"],
+    ["somewhat ./\\ special", "somewhat \\./\\\\ special"],
+    [
+      "extra special ^$\\.*+?()[]{}|",
+      "extra special \\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|",
+    ],
+  ];
+  for (const [raw, escaped] of testCases) {
+    it(`should escape "${raw}" to "${escaped}"`, () => {
+      expect(regexpEscape(raw)).toEqual(escaped);
+    });
+  }
+});