Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Changelog/v1.2.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@
- Widget integrations can prefill the editable reporter name and email through `BugPin.init()` or script-tag data attributes.
- Reporter-prefilled drafts are scoped by reporter email to avoid restoring another reporter's saved form data.
- The Admin Console's Test Widget page now lets administrators edit the test reporter and switch between reporter and logged-out modes.

### Fixes

- GitHub webhook deliveries to `POST /api/webhooks/github/:integrationId` are no longer rejected with session `UNAUTHORIZED` before signature validation. The inbound GitHub route is mounted ahead of authenticated outbound webhook management, so GitHub authenticates with `X-Hub-Signature-256` as intended.
4 changes: 1 addition & 3 deletions src/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function createApiRouter(): Hono {
api.route('/integrations', integrationsRoutes);
api.route('/notification-preferences', notificationPreferences);
api.route('/license', licenseRoutes);
api.route('/webhooks/github', githubWebhookRoutes);

// Mount EE routes first if available (they take priority over CE routes)
// EE routes handle the actual feature implementation when licensed
Expand Down Expand Up @@ -77,9 +78,6 @@ export function createApiRouter(): Hono {
// Mount widget routes (public)
api.route('/widget', widgetRoutes);

// Mount GitHub webhook routes (public, no auth)
api.route('/webhooks/github', githubWebhookRoutes);

// Mount public files routes (public, no auth)
api.route('/public/files', publicFilesRoutes);

Expand Down
26 changes: 26 additions & 0 deletions tests/server/routes/github-webhook.routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,30 @@ describe('github-webhook routes', () => {
expect(res.status).toBe(200);
});
});

describe('API router mount order', () => {
it('reaches the GitHub handler when mounted before authenticated /webhooks', async () => {
const { webhooksRoutes } = await import('../../../src/server/routes/api/webhooks');
const app = new Hono();
app.route('/webhooks/github', githubWebhookRoutes);
app.route('/webhooks', webhooksRoutes);

const res = await app.request('http://localhost/webhooks/github/int_1', {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-github-event': 'ping',
'x-github-delivery': 'delivery_1',
},
body: JSON.stringify({ zen: 'test' }),
});

const body = (await res.json()) as { error?: string; message?: string };

expect(body.error).not.toBe('UNAUTHORIZED');
expect(body.message).not.toBe('Authentication required');
expect(res.status).toBe(401);
expect(body.error).toBe('Missing signature');
});
});
});