Skip to content

fix(jira): fail closed when webhook secret or signature is missing - #608

Merged
devjain32 merged 7 commits into
corsairdev:mainfrom
sushantlokhande14:fix/jira-webhook-fail-open
Aug 6, 2026
Merged

fix(jira): fail closed when webhook secret or signature is missing#608
devjain32 merged 7 commits into
corsairdev:mainfrom
sushantlokhande14:fix/jira-webhook-fail-open

Conversation

@sushantlokhande14

@sushantlokhande14 sushantlokhande14 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #595.

verifyJiraWebhookSignature returned { valid: true } for any request with no x-hub-signature header, as long as no secret was configured — so omitting the signature header bypassed verification entirely.

// before
if (!signatureHeader) {
	// Only allow unsigned requests when no secret has been configured
	if (!secret) {
		return { valid: true };   // <-- fail open
	}
	return { valid: false, error: 'Missing x-hub-signature header' };
}

Now the secret is checked first and a missing header is never valid, so neither a missing secret nor a missing signature can resolve to valid: true:

// after
if (!secret) {
	return { valid: false, error: 'Missing webhook secret' };
}
...
if (!signatureHeader) {
	return { valid: false, error: 'Missing x-hub-signature header' };
}

I deliberately matched the ordering and error strings already used by verifySpotifyWebhookSignature, since that verifier was fixed for this same fail-open family (#519, #520, #514) — so all the plugins now read the same way.

Adds packages/jira/webhooks/types.test.ts, mirroring the Spotify verifier's test layout:

case expected
secret missing (header present) Missing webhook secret
secret and header both missing valid: false — this is the actual bypass
header missing (secret present) Missing x-hub-signature header
signature signed with a different key Invalid signature
signature of the wrong length Signature length mismatch
correct signature round-trip valid: true
header supplied as string[] valid: true

All four acceptance criteria in the issue are covered.

Checklist

  • I have run pnpm lint and all checks pass — biome check is clean on both changed files, and the repo's own lint-staged hook (biome check --write) ran clean on both commits
  • I have run pnpm typecheck and there are no TypeScript errors — tsc --build exits 0; the repo's pre-push typecheck hook also passed
  • I have run pnpm build and all packages build successfully — pnpm --filter @corsair-dev/jira build succeeds
  • I have run pnpm test and all tests pass — green in CI; see note below for local runs
  • I have added or updated tests where applicable
  • I have added or updated necessary documentation — none required, no public API or plugin option changed

Two notes so the ticks above are not taken on trust:

Tests. My new suite passes 7/7, but the pre-existing packages/jira/api.test.ts fails 12/12 on a clean checkout of main too, because it builds an auth header from an unset API key (Buffer.from(apiKey)TypeError: ... Received undefined). Unrelated to this change; I left it alone. Happy to fix it in a separate PR if useful.

Lint. I verified biome check on the two files I changed rather than repo-wide, because I'm on a Windows checkout where core.autocrlf gives every file CRLF and repo-wide biome check . therefore fails identically on unmodified main. Git normalises to LF on commit, so the diff itself carries no line-ending changes — git diff --stat on the branch is +117 / -4 across exactly two files.

# on clean main:            Test Suites: 1 failed, 1 total   Tests: 12 failed, 12 total
# on this branch:           Test Suites: 1 failed, 1 passed  Tests: 12 failed, 7 passed
#                                                     ^ pre-existing        ^ new, all passing

Screenshots / Demos (if applicable)

On R4 in PLUGIN_PR_RULES.md: the rule exists because "neither CI nor review bots can call the real third-party API." That doesn't apply here — this changes a pure local HMAC comparison, calls no Jira endpoint, and needs no credentials (the issue notes this too). The unit tests are the verification, and they run in CI. Terminal output:

$ npx jest --config packages/jira/jest.config.cjs webhooks/types.test.ts

 PASS  packages/jira/webhooks/types.test.ts
  verifyJiraWebhookSignature
    ✓ should fail closed when secret is missing
    ✓ should fail closed when both secret and signature header are missing
    ✓ should return invalid if signature header is missing
    ✓ should return invalid if signature does not match
    ✓ should return invalid if the signature length does not match
    ✓ should return valid for a correct signature round-trip
    ✓ should accept the signature header when provided as an array

Tests:       7 passed, 7 total

Working proof: the CI run for this branch, where the suite executes and passes — CI Checks.

To be straight about it: that is a link to a CI job, not a screen recording. I can't record one, and for this change there is nothing to film — no UI, no CLI output, no third-party call. If a recording is required regardless, say so and I'll arrange it.

Additional Notes

  • Scope is packages/jira/** only (R1) — no changes to constants.ts or the lockfile were needed.
  • No breaking change for correctly-configured webhooks: a request with a valid signature and a configured secret behaves exactly as before. The behaviour that changes is precisely the insecure one — a deployment relying on unsigned webhooks with no secret set will now be rejected, which is the point of the fix.
  • fix(gitlab): webhook signature verification fails open when secret is missing #594 is the same fail-open bug in the GitLab verifier; I'll send that as a separate PR to keep one plugin per PR.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Jira webhook signature validation to fail fast when the webhook secret is missing.
    • Added clearer validation handling for missing, invalid, mismatched, and array-based signature headers.
    • Verified successful validation for correctly signed webhook requests.

verifyJiraWebhookSignature returned { valid: true } for any request with
no x-hub-signature header, as long as no secret was configured. An
attacker only had to omit the signature header to bypass verification
entirely.

Check the secret first and never treat a missing header as valid, so
neither a missing secret nor a missing signature can resolve to valid.
This matches the shape already used by the Spotify verifier after the
same fail-open family was fixed there (corsairdev#519, corsairdev#520, corsairdev#514).

Fixes corsairdev#595
Adds packages/jira/webhooks/types.test.ts, mirroring the Spotify
verifier's test layout: missing secret, missing signature header, the
both-missing case that was the actual bypass, wrong signature, length
mismatch, a correct round-trip, and the array-valued header form.

Fixes corsairdev#595
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
www Skipped Skipped Aug 6, 2026 2:06pm

Request Review

@github-actions github-actions Bot added the plugin Changes inside a plugin package label Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fab20669-4035-4b6f-93f4-c2e2c1549c08

📥 Commits

Reviewing files that changed from the base of the PR and between a389c86 and 7c097a0.

📒 Files selected for processing (2)
  • packages/jira/webhooks/types.test.ts
  • packages/jira/webhooks/types.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/jira/webhooks/types.ts
  • packages/jira/webhooks/types.test.ts

📝 Walkthrough

Walkthrough

Jira webhook signature verification now rejects requests without a webhook secret. New tests cover missing inputs, invalid signatures, valid HMAC-SHA256 signatures, length mismatches, and array-valued headers.

Changes

Jira webhook verification

Layer / File(s) Summary
Fail-closed verification and coverage
packages/jira/webhooks/types.ts, packages/jira/webhooks/types.test.ts
verifyJiraWebhookSignature returns valid: false with Missing webhook secret when no secret is configured. Tests cover missing secrets, missing headers, invalid and mismatched signatures, valid signatures, and array-valued headers.

Estimated code review effort: 3 (Moderate) | ~15–30 minutes

Possibly related PRs

Suggested reviewers: yuvrxj-afk

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Jira webhook security fix for missing secrets or signatures.
Linked Issues check ✅ Passed The changes reject missing secrets and signatures, preserve valid verification, and add the required unit tests for issue #595.
Out of Scope Changes check ✅ Passed All implementation and test changes directly support the Jira webhook verification requirements in issue #595.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR closes Jira webhook verification when either the configured secret or request signature is missing.

  • Checks for a missing webhook secret before processing signature headers.
  • Removes the previous unsigned-request success path.
  • Adds seven unit tests covering missing configuration, absent and invalid signatures, length mismatch, valid signatures, and array-valued headers.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/jira/webhooks/types.ts Reorders validation to reject a missing secret before signature processing and preserves compatibility with existing webhook handlers.
packages/jira/webhooks/types.test.ts Adds focused assertions covering the fail-closed regression and the verifier's principal signature-validation outcomes.

Reviews (2): Last reviewed commit: "fix(jira): tighten fail-closed webhook s..." | Re-trigger Greptile

@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile review

@devjain32
devjain32 merged commit c910089 into corsairdev:main Aug 6, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin Changes inside a plugin package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(jira): webhook signature verification fails open when secret and signature header are both missing

3 participants