Modify Origin header validation in validateRequestHeaders (streamableHttp.ts and sse.ts) to allow requests without an Origin, as they are not relevant to server DNS rebinding protection. (#1205)
This commit is contained in:
parent
a6ee2cb3c2
commit
608360047d
4 changed files with 46 additions and 2 deletions
|
|
@ -547,6 +547,27 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
|
|||
expect(mockHandleRes.end).toHaveBeenCalledWith('Accepted');
|
||||
});
|
||||
|
||||
it('should accept requests without origin headers', async () => {
|
||||
const mockRes = createMockResponse();
|
||||
const transport = new SSEServerTransport('/messages', mockRes, {
|
||||
allowedOrigins: ['http://localhost:3000', 'https://example.com'],
|
||||
enableDnsRebindingProtection: true
|
||||
});
|
||||
await transport.start();
|
||||
|
||||
const mockReq = createMockRequest({
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
});
|
||||
const mockHandleRes = createMockResponse();
|
||||
|
||||
await transport.handlePostMessage(mockReq, mockHandleRes, { jsonrpc: '2.0', method: 'test' });
|
||||
|
||||
expect(mockHandleRes.writeHead).toHaveBeenCalledWith(202);
|
||||
expect(mockHandleRes.end).toHaveBeenCalledWith('Accepted');
|
||||
});
|
||||
|
||||
it('should reject requests with disallowed origin headers', async () => {
|
||||
const mockRes = createMockResponse();
|
||||
const transport = new SSEServerTransport('/messages', mockRes, {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export class SSEServerTransport implements Transport {
|
|||
// Validate Origin header if allowedOrigins is configured
|
||||
if (this._options.allowedOrigins && this._options.allowedOrigins.length > 0) {
|
||||
const originHeader = req.headers.origin;
|
||||
if (!originHeader || !this._options.allowedOrigins.includes(originHeader)) {
|
||||
if (originHeader && !this._options.allowedOrigins.includes(originHeader)) {
|
||||
return `Invalid Origin header: ${originHeader}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2678,6 +2678,29 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
|
|||
const body = await response.json();
|
||||
expect(body.error.message).toBe('Invalid Origin header: http://evil.com');
|
||||
});
|
||||
|
||||
it('should accept requests without origin headers', async () => {
|
||||
const result = await createTestServerWithDnsProtection({
|
||||
sessionIdGenerator: undefined,
|
||||
allowedOrigins: ['http://localhost:3000', 'https://example.com'],
|
||||
enableDnsRebindingProtection: true
|
||||
});
|
||||
server = result.server;
|
||||
transport = result.transport;
|
||||
baseUrl = result.baseUrl;
|
||||
|
||||
const response = await fetch(baseUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json, text/event-stream'
|
||||
},
|
||||
body: JSON.stringify(TEST_MESSAGES.initialize)
|
||||
});
|
||||
|
||||
// Should pass even with no Origin headers because requests that do not come from browsers may not have Origin and DNS rebinding attacks can only be performed via browsers
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('enableDnsRebindingProtection option', () => {
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
// Validate Origin header if allowedOrigins is configured
|
||||
if (this._allowedOrigins && this._allowedOrigins.length > 0) {
|
||||
const originHeader = req.headers.origin;
|
||||
if (!originHeader || !this._allowedOrigins.includes(originHeader)) {
|
||||
if (originHeader && !this._allowedOrigins.includes(originHeader)) {
|
||||
return `Invalid Origin header: ${originHeader}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue