feat(webhook): add JIRA webhook HMAC-SHA256 signature verification#978
Merged
feat(webhook): add JIRA webhook HMAC-SHA256 signature verification#978
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
nhopeatall
approved these changes
Mar 22, 2026
Collaborator
nhopeatall
left a comment
There was a problem hiding this comment.
Summary
LGTM — Clean, well-structured implementation that correctly mirrors the existing GitHub and Trello webhook signature verification patterns.
What I verified:
verifyJiraSignature()correctly uses HMAC-SHA256 withtimingSafeEqualand a length guard before comparison — identical approach toverifyGitHubSignature().verifyJiraWebhookSignature()follows the exact same callback pattern as the GitHub/Trello equivalents: extract identifier from payload → find project → resolve secret → verify (or skip when no secret/project).extractJiraProjectKey()uses the sameissue.fields.project.keypath asJiraRouterAdapter.parseWebhook(), so verification and routing share the same assumptions about payload structure.resolveWebhookSecret()extends cleanly with the'jira'provider, resolving frompmcategory (consistent with JIRA being a PM integration).- The
webhook_secretcredential role is correctly markedoptional: truefor backwards compatibility. - The
nullreturn (skip verification) when no project key is found, no project matches, or no secret is configured is the correct backwards-compatible behavior. - Test coverage is thorough: low-level signature verification, callback-level verification, and end-to-end Hono app tests all covering valid, invalid, and skip scenarios.
- All 7 CI checks pass.
Minor observation (not blocking): For comment_created/comment_updated JIRA events that may lack issue.fields.project.key, signature verification is silently skipped. This is consistent with how JiraRouterAdapter.parseWebhook() also returns null for these payloads (so they wouldn't be processed anyway), making it a non-issue in practice.
🕵️ claude-code · claude-opus-4-6 · run details
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
verifyJiraSignature()tosrc/webhook/signatureVerification.tsusing HMAC-SHA256 with timing-safe comparison, following the exact same pattern asverifyGitHubSignature()verifyJiraWebhookSignature()tosrc/router/webhookVerification.tsas averifySignaturecallback that resolves the project from the JIRA project key in the payload, looks up the webhook secret, and verifies theX-Hub-SignatureheaderverifyJiraWebhookSignatureinto the JIRAcreateWebhookHandler()call insrc/router/index.ts(previously missing — unlike GitHub and Trello which both had verification)resolveWebhookSecret()in credentials.ts to accept'jira'as a provider (resolveswebhook_secretfrom the PM integration)webhook_secret(optional) to JIRA credential roles inintegrationRoles.tsTest plan
verifyJiraSignature()unit tests: valid signature, invalid signature, missing/bad prefix, tampered body, empty body, garbage input, timing-safe length mismatchverifyJiraWebhookSignature()unit tests: valid sig, wrong sig, missing header (with secret), no secret (skip), project not found (skip), missing project key (skip)extractJiraProjectKey()unit tests: extracts key, handles missing fields, handles invalid JSONTrello card: https://trello.com/c/4X6eqQSR/499-as-a-developer-i-want-jira-webhook-signature-verification-so-that-spoofed-jira-webhooks-are-rejected
🤖 Generated with Claude Code
🕵️ claude-code · claude-sonnet-4-6 · run details