Skip to content

Commit c4fe312

Browse files
Merge pull request #136 from leanix/feature/CID-4118/Validate-webhook-signature-before-removing-it
CID-4118: Validate webhook signature
2 parents fd6a9a5 + 283477b commit c4fe312

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

src/main/kotlin/net/leanix/githubagent/services/GitHubWebhookService.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ class GitHubWebhookService(
6060
logger.error("Invalid signature format, expected 'sha256=' prefix")
6161
throw InvalidEventSignatureException()
6262
}
63+
64+
val signatureWithoutPrefix = signature256.removePrefix("sha256=")
65+
if (!signatureWithoutPrefix.matches(Regex("^[a-fA-F0-9]{64}$"))) {
66+
logger.error("Invalid signature format, expected a 64-character hexadecimal string after 'sha256='")
67+
throw InvalidEventSignatureException()
68+
}
69+
6370
val hashedSecret = hmacSHA256(gitHubEnterpriseProperties.webhookSecret, payload)
6471
val isEqual = timingSafeEqual(signature256.removePrefix("sha256="), hashedSecret)
6572
if (!isEqual) throw InvalidEventSignatureException()

src/test/kotlin/net/leanix/githubagent/services/GitHubWebhookServiceTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,27 @@ class GitHubWebhookServiceTest {
9999
gitHubWebhookService.handleWebhookEvent("PUSH", "known.host", "invalid_signature", "{}")
100100
}
101101
}
102+
103+
@Test
104+
fun `should process event with valid signature from event json`() {
105+
val payload = """{
106+
"action": "created",
107+
"installation": {
108+
"id": 30,
109+
"account": {
110+
"login": "test-org",
111+
"id": 20
112+
}
113+
}
114+
}"""
115+
val secret = "secret"
116+
val validSignature = "sha256=042fb14dec4f623e224b1b574e40ff776c341fcd883756256d786a1b95bb3aa8"
117+
every { gitHubEnterpriseProperties.baseUrl } returns "known.host"
118+
every { gitHubEnterpriseProperties.webhookSecret } returns secret
119+
every { webhookEventService.consumeWebhookEvent(any(), any()) } returns Unit
120+
121+
gitHubWebhookService.handleWebhookEvent("PUSH", "known.host", validSignature, payload)
122+
123+
verify { webhookEventService.consumeWebhookEvent("PUSH", payload) }
124+
}
102125
}

0 commit comments

Comments
 (0)