diff --git a/frontend/src/metabase/components/FieldValuesWidget.jsx b/frontend/src/metabase/components/FieldValuesWidget.jsx
index ba08d7abcefa2b26ea469c32be8a58bee52606d7..5af49a7af6df36cdd5c2f690f919c97e9275007d 100644
--- a/frontend/src/metabase/components/FieldValuesWidget.jsx
+++ b/frontend/src/metabase/components/FieldValuesWidget.jsx
@@ -481,8 +481,9 @@ export class FieldValuesWidget extends Component {
               }
               // if the field is numeric we need to parse the string into an integer
               if (fields[0].isNumeric()) {
-                if (/^-?\d+(\.\d+)?$/.test(v)) {
-                  return parseFloat(v);
+                const n = Number.parseFloat(v);
+                if (Number.isFinite(n)) {
+                  return n;
                 } else {
                   return null;
                 }
diff --git a/frontend/src/metabase/components/TokenField.jsx b/frontend/src/metabase/components/TokenField.jsx
index 5dca1bf410c430b29bd9cde1230409c2051321b9..a89f4e2390ec9f53bfe83dd68fcf83fab81be8d0 100644
--- a/frontend/src/metabase/components/TokenField.jsx
+++ b/frontend/src/metabase/components/TokenField.jsx
@@ -300,12 +300,8 @@ export default class TokenField extends Component {
     if (this.props.parseFreeformValue) {
       e.preventDefault();
       const string = e.clipboardData.getData("Text");
-      const values = this.props.multi
-        ? string
-            .split(/\n|,/g)
-            .map(this.props.parseFreeformValue)
-            .filter(s => s)
-        : [string];
+      const lines = this.props.multi ? string.split(/\n|,/g) : [string];
+      const values = lines.map(this.props.parseFreeformValue).filter(s => s);
       if (values.length > 0) {
         this.addValue(values);
       }
diff --git a/frontend/test/metabase/scenarios/filters/reproductions/9339-clipboard-numeric-filter.cy.spec.js b/frontend/test/metabase/scenarios/filters/reproductions/9339-clipboard-numeric-filter.cy.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..f57f47fa8b677bf045129d3da35fa566ed455b7b
--- /dev/null
+++ b/frontend/test/metabase/scenarios/filters/reproductions/9339-clipboard-numeric-filter.cy.spec.js
@@ -0,0 +1,26 @@
+import { openOrdersTable, restore } from "__support__/e2e/cypress";
+
+describe("issue 9339", () => {
+  beforeEach(() => {
+    restore();
+    cy.signInAsAdmin();
+  });
+
+  it("should not paste non-numeric values into single-value numeric filters (metabase#9339)", () => {
+    openOrdersTable();
+
+    cy.findByText("Total").click();
+    cy.findByText("Filter by this column").click();
+    cy.findByText("Equal to").click();
+    cy.findByText("Greater than").click();
+
+    paste(cy.findByPlaceholderText("Enter a number"), "9339,1234");
+    cy.findByText("9,339").should("be.visible");
+    cy.findByText("1,234").should("not.exist");
+    cy.button("Add filter").should("be.enabled");
+  });
+});
+
+const paste = (selection, text) => {
+  selection.trigger("paste", { clipboardData: { getData: () => text } });
+};