From 5ebb98debea468140eab18235180030323d7fd73 Mon Sep 17 00:00:00 2001 From: Nepomuk Crhonek <105591323+Nepomuk5665@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:00:02 +0100 Subject: [PATCH] Fix unhandled NumberFormatException in webhook timestamp parsing When parsing the Stripe-Signature header, getTimestamp() calls Long.parseLong() on the timestamp value without catching NumberFormatException. If a malformed header contains a non-numeric timestamp value (e.g., 't=not_a_number'), the exception propagates up uncaught, rather than being wrapped in a SignatureVerificationException as documented. This commit catches NumberFormatException and returns -1, which causes verifyHeader() to throw the expected SignatureVerificationException with the message 'Unable to extract timestamp and signatures from header'. Also adds a test case for malformed timestamp values. --- src/main/java/com/stripe/net/Webhook.java | 6 +++++- src/test/java/com/stripe/net/WebhookTest.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/stripe/net/Webhook.java b/src/main/java/com/stripe/net/Webhook.java index ea67ea34362..72284fb05ea 100644 --- a/src/main/java/com/stripe/net/Webhook.java +++ b/src/main/java/com/stripe/net/Webhook.java @@ -176,7 +176,11 @@ private static long getTimestamp(String sigHeader) { for (String item : items) { String[] itemParts = item.split("=", 2); if (itemParts[0].equals("t")) { - return Long.parseLong(itemParts[1]); + try { + return Long.parseLong(itemParts[1]); + } catch (NumberFormatException e) { + return -1; + } } } diff --git a/src/test/java/com/stripe/net/WebhookTest.java b/src/test/java/com/stripe/net/WebhookTest.java index c6a9c89aa77..8802fbb5f75 100644 --- a/src/test/java/com/stripe/net/WebhookTest.java +++ b/src/test/java/com/stripe/net/WebhookTest.java @@ -160,6 +160,21 @@ public void testMalformedHeader() throws SignatureVerificationException { assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage()); } + @Test + public void testMalformedTimestampValue() throws SignatureVerificationException { + // Test with non-numeric timestamp value - should throw SignatureVerificationException, + // not NumberFormatException + final String sigHeader = "t=not_a_number,v1=somesignature"; + + Throwable exception = + assertThrows( + SignatureVerificationException.class, + () -> { + Webhook.Signature.verifyHeader(payload, sigHeader, secret, 0, null); + }); + assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage()); + } + @Test public void testNoSignaturesWithExpectedScheme() throws SignatureVerificationException, NoSuchAlgorithmException, InvalidKeyException {