fix: validate response in protocol.handle()
(#38587)
fix: validate response in protocol.handle()
This commit is contained in:
parent
5931f69f18
commit
86824c070e
2 changed files with 61 additions and 4 deletions
|
@ -60,6 +60,26 @@ function convertToRequestBody (uploadData: ProtocolRequest['uploadData']): Reque
|
|||
}) as RequestInit['body'];
|
||||
}
|
||||
|
||||
// TODO(codebytere): Use Object.hasOwn() once we update to ECMAScript 2022.
|
||||
function validateResponse (res: Response) {
|
||||
if (!res || typeof res !== 'object') return false;
|
||||
|
||||
if (res.type === 'error') return true;
|
||||
|
||||
const exists = (key: string) => Object.prototype.hasOwnProperty.call(res, key);
|
||||
|
||||
if (exists('status') && typeof res.status !== 'number') return false;
|
||||
if (exists('statusText') && typeof res.statusText !== 'string') return false;
|
||||
if (exists('headers') && typeof res.headers !== 'object') return false;
|
||||
|
||||
if (exists('body')) {
|
||||
if (typeof res.body !== 'object') return false;
|
||||
if (res.body !== null && !(res.body instanceof ReadableStream)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Protocol.prototype.handle = function (this: Electron.Protocol, scheme: string, handler: (req: Request) => Response | Promise<Response>) {
|
||||
const register = isBuiltInScheme(scheme) ? this.interceptProtocol : this.registerProtocol;
|
||||
const success = register.call(this, scheme, async (preq: ProtocolRequest, cb: any) => {
|
||||
|
@ -73,13 +93,14 @@ Protocol.prototype.handle = function (this: Electron.Protocol, scheme: string, h
|
|||
duplex: body instanceof ReadableStream ? 'half' : undefined
|
||||
} as any);
|
||||
const res = await handler(req);
|
||||
if (!res || typeof res !== 'object') {
|
||||
if (!validateResponse(res)) {
|
||||
return cb({ error: ERR_UNEXPECTED });
|
||||
}
|
||||
if (res.type === 'error') { cb({ error: ERR_FAILED }); } else {
|
||||
} else if (res.type === 'error') {
|
||||
cb({ error: ERR_FAILED });
|
||||
} else {
|
||||
cb({
|
||||
data: res.body ? Readable.fromWeb(res.body as ReadableStream<ArrayBufferView>) : null,
|
||||
headers: Object.fromEntries(res.headers),
|
||||
headers: res.headers ? Object.fromEntries(res.headers) : {},
|
||||
statusCode: res.status,
|
||||
statusText: res.statusText,
|
||||
mimeType: (res as any).__original_resp?._responseHead?.mimeType
|
||||
|
|
|
@ -1211,6 +1211,42 @@ describe('protocol module', () => {
|
|||
await expect(net.fetch('test-scheme://foo')).to.eventually.be.rejectedWith('net::ERR_FAILED');
|
||||
});
|
||||
|
||||
it('handles invalid protocol response status', async () => {
|
||||
protocol.handle('test-scheme', () => {
|
||||
return { status: [] } as any;
|
||||
});
|
||||
|
||||
defer(() => { protocol.unhandle('test-scheme'); });
|
||||
await expect(net.fetch('test-scheme://foo')).to.be.rejectedWith('net::ERR_UNEXPECTED');
|
||||
});
|
||||
|
||||
it('handles invalid protocol response statusText', async () => {
|
||||
protocol.handle('test-scheme', () => {
|
||||
return { statusText: false } as any;
|
||||
});
|
||||
|
||||
defer(() => { protocol.unhandle('test-scheme'); });
|
||||
await expect(net.fetch('test-scheme://foo')).to.be.rejectedWith('net::ERR_UNEXPECTED');
|
||||
});
|
||||
|
||||
it('handles invalid protocol response header parameters', async () => {
|
||||
protocol.handle('test-scheme', () => {
|
||||
return { headers: false } as any;
|
||||
});
|
||||
|
||||
defer(() => { protocol.unhandle('test-scheme'); });
|
||||
await expect(net.fetch('test-scheme://foo')).to.be.rejectedWith('net::ERR_UNEXPECTED');
|
||||
});
|
||||
|
||||
it('handles invalid protocol response body parameters', async () => {
|
||||
protocol.handle('test-scheme', () => {
|
||||
return { body: false } as any;
|
||||
});
|
||||
|
||||
defer(() => { protocol.unhandle('test-scheme'); });
|
||||
await expect(net.fetch('test-scheme://foo')).to.be.rejectedWith('net::ERR_UNEXPECTED');
|
||||
});
|
||||
|
||||
it('handles a synchronous error in the handler', async () => {
|
||||
protocol.handle('test-scheme', () => { throw new Error('test'); });
|
||||
defer(() => { protocol.unhandle('test-scheme'); });
|
||||
|
|
Loading…
Reference in a new issue