Skip to content

Commit c89717b

Browse files
committed
feat(webhook): expand internal fields filtering in webhook payload
1 parent 1f21746 commit c89717b

2 files changed

Lines changed: 35 additions & 7 deletions

File tree

workers/webhook/src/templates/generic.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@ import { Notification } from 'hawk-worker-sender/types/template-variables';
22
import { WebhookDelivery } from '../../types/template';
33

44
/**
5-
* List of internal fields that should not be exposed in webhook payload
5+
* Internal/sensitive fields stripped from webhook payload at any nesting level
66
*/
7-
const INTERNAL_FIELDS = new Set(['host', 'hostOfStatic']);
7+
const INTERNAL_FIELDS = new Set([
8+
'host',
9+
'hostOfStatic',
10+
'token',
11+
'notifications',
12+
'integrationId',
13+
'notificationRuleId',
14+
'visitedBy',
15+
'uidAdded',
16+
]);
817

918
/**
1019
* Recursively converts MongoDB ObjectIds and other non-JSON-safe values to strings

workers/webhook/tests/provider.test.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,43 @@ describe('WebhookProvider', () => {
6161
expect(deliver.mock.calls[0][1].type).toBe('assignee');
6262
});
6363

64-
it('should strip internal fields (host, hostOfStatic) from payload', async () => {
64+
it('should strip all internal/sensitive fields from payload', async () => {
6565
const provider = new WebhookProvider();
6666

6767
await provider.send(webhookEndpointSample, {
68-
type: 'payment-failed',
68+
type: 'event',
6969
payload: {
7070
host: 'https://garage.hawk.so',
7171
hostOfStatic: 'https://api.hawk.so',
72-
workspace: { name: 'Workspace' },
73-
reason: 'Insufficient funds',
72+
notificationRuleId: '123',
73+
project: {
74+
name: 'My Project',
75+
token: 'secret-token',
76+
integrationId: 'uuid',
77+
uidAdded: 'user-id',
78+
notifications: [{ rule: 'data' }],
79+
},
80+
events: [{
81+
event: {
82+
groupHash: 'abc',
83+
visitedBy: ['user1'],
84+
},
85+
}],
7486
},
7587
} as any);
7688

7789
const delivery = deliver.mock.calls[0][1];
7890

7991
expect(delivery.payload).not.toHaveProperty('host');
8092
expect(delivery.payload).not.toHaveProperty('hostOfStatic');
81-
expect(delivery.payload).toHaveProperty('reason', 'Insufficient funds');
93+
expect(delivery.payload).not.toHaveProperty('notificationRuleId');
94+
expect(delivery.payload.project).not.toHaveProperty('token');
95+
expect(delivery.payload.project).not.toHaveProperty('integrationId');
96+
expect(delivery.payload.project).not.toHaveProperty('uidAdded');
97+
expect(delivery.payload.project).not.toHaveProperty('notifications');
98+
expect(delivery.payload.project).toHaveProperty('name', 'My Project');
99+
expect((delivery.payload.events as any[])[0].event).not.toHaveProperty('visitedBy');
100+
expect((delivery.payload.events as any[])[0].event).toHaveProperty('groupHash', 'abc');
82101
});
83102

84103
it('should handle all known notification types without throwing', async () => {

0 commit comments

Comments
 (0)