Skip to content

Commit

Permalink
add integrity header to delivery-fetch sendSession
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Skinner committed Oct 18, 2024
1 parent 6409517 commit c8f48cc
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 21 deletions.
42 changes: 25 additions & 17 deletions packages/delivery-fetch/delivery.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import payload from '@bugsnag/core/lib/json-payload'

async function addIntegrityHeader (windowOrWorkerGlobalScope, requestBody, headers) {
function addIntegrityHeader (windowOrWorkerGlobalScope, requestBody, headers) {
if (windowOrWorkerGlobalScope.isSecureContext && windowOrWorkerGlobalScope.crypto && windowOrWorkerGlobalScope.crypto.subtle && windowOrWorkerGlobalScope.crypto.subtle.digest && typeof TextEncoder === 'function') {
const msgUint8 = new TextEncoder().encode(requestBody)
const hashBuffer = await windowOrWorkerGlobalScope.crypto.subtle.digest('SHA-1', msgUint8)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
return windowOrWorkerGlobalScope.crypto.subtle.digest('SHA-1', msgUint8).then((hashBuffer) => {
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, '0'))
.join('')

headers['Bugsnag-Integrity'] = 'sha1 ' + hashHex
headers['Bugsnag-Integrity'] = 'sha1 ' + hashHex
})
}

return Promise.resolve()
}

const delivery = (client, fetch = global.fetch, windowOrWorkerGlobalScope = window) => ({
Expand Down Expand Up @@ -41,16 +44,21 @@ const delivery = (client, fetch = global.fetch, windowOrWorkerGlobalScope = wind
sendSession: (session, cb = () => { }) => {
const url = client._config.endpoints.sessions

fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Bugsnag-Api-Key': client._config.apiKey,
'Bugsnag-Payload-Version': '1',
'Bugsnag-Sent-At': (new Date()).toISOString()
},
body: payload.session(session, client._config.redactedKeys)
}).then(() => {
const body = payload.session(session, client._config.redactedKeys)
const headers = {
'Content-Type': 'application/json',
'Bugsnag-Api-Key': client._config.apiKey,
'Bugsnag-Payload-Version': '1',
'Bugsnag-Sent-At': (new Date()).toISOString()
}

addIntegrityHeader(windowOrWorkerGlobalScope, body, headers).then(() =>
fetch(url, {
method: 'POST',
headers,
body
})
).then(() => {
cb(null)
}).catch(err => {
client._logger.error(err)
Expand Down
9 changes: 7 additions & 2 deletions packages/delivery-fetch/test/delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('delivery:fetch', () => {

const payload = { sample: 'payload' } as unknown as EventDeliveryPayload

delivery({ logger: { }, _config: config } as unknown as Client).sendEvent(payload, (err) => {
delivery({ logger: {}, _config: config } as unknown as Client).sendEvent(payload, (err) => {
expect(err).toBeNull()
expect(globalAny.fetch).toHaveBeenCalled()
expect(globalAny.fetch).toHaveBeenCalledWith('/echo/', expect.objectContaining({
Expand Down Expand Up @@ -81,6 +81,8 @@ describe('delivery:fetch', () => {
})

it('sends sessions successfully', done => {
window.isSecureContext = true

globalAny.fetch = jest.fn(() => Promise.resolve({
json: () => Promise.resolve()
}))
Expand All @@ -102,11 +104,14 @@ describe('delivery:fetch', () => {
'Bugsnag-Api-Key': 'aaaaaaaa',
'Bugsnag-Payload-Version': '1',
'Bugsnag-Sent-At': expect.stringMatching(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/),
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'Bugsnag-Integrity': 'sha1 14faf2461b0519f9d9d62cfb8d79483fcc8f825c'
})
}))
done()
})

window.isSecureContext = false
})

it('returns an error for failed sessions', done => {
Expand Down
6 changes: 4 additions & 2 deletions packages/delivery-xml-http-request/test/delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,10 @@ describe('delivery:XMLHttpRequest', () => {
const config = {
apiKey: 'aaaaaaaa',
endpoints: { notify: '/', sessions: '/echo/' },
redactedKeys: []
redactedKeys: [],
sendPayloadChecksums: true
}
delivery({ _config: config, _logger: {} } as unknown as Client, { XMLHttpRequest } as unknown as Window).sendSession(payload, (err) => {
delivery({ _config: config, _logger: {} } as unknown as Client, { ...window, XMLHttpRequest, isSecureContext: true } as unknown as Window).sendSession(payload, (err) => {
expect(err).toBe(null)
expect(requests.length).toBe(1)
expect(requests[0].method).toBe('POST')
Expand All @@ -356,6 +357,7 @@ describe('delivery:XMLHttpRequest', () => {
expect(requests[0].headers['Bugsnag-Api-Key']).toEqual('aaaaaaaa')
expect(requests[0].headers['Bugsnag-Payload-Version']).toEqual('1')
expect(requests[0].headers['Bugsnag-Sent-At']).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/)
expect(requests[0].headers['Bugsnag-Integrity']).toEqual('sha1 14faf2461b0519f9d9d62cfb8d79483fcc8f825c')
expect(requests[0].data).toBe(JSON.stringify(payload))
done()
})
Expand Down

0 comments on commit c8f48cc

Please sign in to comment.