Skip to content

Commit 3f1997f

Browse files
Fix NumberFormatException in Webhook.Signature.getTimestamp
Webhook.Signature.getTimestamp() calls Long.parseLong() on the raw timestamp value from the signature header without any error handling. If a malformed webhook header arrives with a non-numeric timestamp (e.g. t=abc,v1=sig...), the SDK throws an unhandled NumberFormatException instead of a proper SignatureVerificationException. This change wraps the Long.parseLong() call in a try-catch that returns -1 on NumberFormatException, which the caller (verifyHeader) already handles by throwing a SignatureVerificationException with a descriptive message. Added tests for: - Non-numeric timestamp values - Empty timestamp values - Overflow timestamp values (exceeding Long.MAX_VALUE) Fixes stripe#2149 Co-Authored-By: Jason Kelley <kllyjsn@gmail.com>
1 parent 3ae83bb commit 3f1997f

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

src/main/java/com/stripe/net/Webhook.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ private static long getTimestamp(String sigHeader) {
183183
for (String item : items) {
184184
String[] itemParts = item.split("=", 2);
185185
if (itemParts[0].equals("t")) {
186-
return Long.parseLong(itemParts[1]);
186+
try {
187+
return Long.parseLong(itemParts[1]);
188+
} catch (NumberFormatException e) {
189+
return -1;
190+
}
187191
}
188192
}
189193

src/test/java/com/stripe/net/WebhookTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,45 @@ public void testMalformedHeader() throws SignatureVerificationException {
160160
assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage());
161161
}
162162

163+
@Test
164+
public void testNonNumericTimestamp() throws SignatureVerificationException {
165+
final String sigHeader = "t=not_a_number,v1=some_signature";
166+
167+
Throwable exception =
168+
assertThrows(
169+
SignatureVerificationException.class,
170+
() -> {
171+
Webhook.Signature.verifyHeader(payload, sigHeader, secret, 0, null);
172+
});
173+
assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage());
174+
}
175+
176+
@Test
177+
public void testEmptyTimestampValue() throws SignatureVerificationException {
178+
final String sigHeader = "t=,v1=some_signature";
179+
180+
Throwable exception =
181+
assertThrows(
182+
SignatureVerificationException.class,
183+
() -> {
184+
Webhook.Signature.verifyHeader(payload, sigHeader, secret, 0, null);
185+
});
186+
assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage());
187+
}
188+
189+
@Test
190+
public void testOverflowTimestampValue() throws SignatureVerificationException {
191+
final String sigHeader = "t=99999999999999999999,v1=some_signature";
192+
193+
Throwable exception =
194+
assertThrows(
195+
SignatureVerificationException.class,
196+
() -> {
197+
Webhook.Signature.verifyHeader(payload, sigHeader, secret, 0, null);
198+
});
199+
assertEquals("Unable to extract timestamp and signatures from header", exception.getMessage());
200+
}
201+
163202
@Test
164203
public void testNoSignaturesWithExpectedScheme()
165204
throws SignatureVerificationException, NoSuchAlgorithmException, InvalidKeyException {

0 commit comments

Comments
 (0)