Skip to content

Commit 078ddca

Browse files
knagaitsevhiroppy
authored andcommitted
fix(server): stricter headers security check (#2092)
* fix(server): stricter headers security check * fix(server): changed comments explaining how server impl works
1 parent 56274e4 commit 078ddca

5 files changed

Lines changed: 109 additions & 3 deletions

File tree

‎lib/Server.js‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,14 @@ class Server {
685685
return;
686686
}
687687

688-
if(headers&&(!this.checkHost(headers)||!this.checkOrigin(headers))){
688+
if(!headers){
689+
this.log.warn(
690+
'serverMode implementation must pass headers to the callback of onConnection(f) '+
691+
'via f(connection, headers) in order for clients to pass a headers security check'
692+
);
693+
}
694+
695+
if(!headers||!this.checkHost(headers)||!this.checkOrigin(headers)){
689696
this.sockWrite([connection],'error','Invalid Host/Origin header');
690697

691698
this.socketServer.close(connection);

‎lib/servers/SockJSServer.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ module.exports = class SockJSServer extends BaseServer {
5757
connection.close();
5858
}
5959

60-
// f should return the resulting connection and, optionally, the connection headers
60+
// f should be passed the resulting connection and the connection headers
6161
onConnection(f){
6262
this.socket.on('connection',(connection)=>{
6363
f(connection,connection.headers);

‎lib/servers/WebsocketServer.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module.exports = class WebsocketServer extends BaseServer {
2727
connection.close();
2828
}
2929

30-
// f should return the resulting connection
30+
// f should be passed the resulting connection and the connection headers
3131
onConnection(f){
3232
this.wsServer.on('connection',(connection,req)=>{
3333
f(connection,req.headers);

‎test/server/__snapshots__/serverMode-option.test.js.snap‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ Array [
77
"close",
88
]
99
`;
10+
11+
exports[`serverMode option without a header results in an error 1`] =`
12+
Array [
13+
"open",
14+
"{\\"type\\":\\"error\\",\\"data\\":\\"Invalid Host/Origin header\\"}",
15+
"close",
16+
]
17+
`;

‎test/server/serverMode-option.test.js‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,95 @@ describe('serverMode option', () => {
223223
},5000);
224224
});
225225
});
226+
227+
describe('without a header',()=>{
228+
letmockWarn;
229+
beforeAll((done)=>{
230+
server=testServer.start(
231+
config,
232+
{
233+
port,
234+
serverMode: classMySockJSServerextendsBaseServer{
235+
constructor(serv){
236+
super(serv);
237+
this.socket=sockjs.createServer({
238+
// Use provided up-to-date sockjs-client
239+
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
240+
// Limit useless logs
241+
log: (severity,line)=>{
242+
if(severity==='error'){
243+
this.server.log.error(line);
244+
}else{
245+
this.server.log.debug(line);
246+
}
247+
},
248+
});
249+
250+
this.socket.installHandlers(this.server.listeningApp,{
251+
prefix: this.server.sockPath,
252+
});
253+
}
254+
255+
send(connection,message){
256+
connection.write(message);
257+
}
258+
259+
close(connection){
260+
connection.close();
261+
}
262+
263+
onConnection(f){
264+
this.socket.on('connection',(connection)=>{
265+
f(connection);
266+
});
267+
}
268+
269+
onConnectionClose(connection,f){
270+
connection.on('close',f);
271+
}
272+
},
273+
},
274+
done
275+
);
276+
277+
mockWarn=jest.spyOn(server.log,'warn').mockImplementation(()=>{});
278+
});
279+
280+
it('results in an error',(done)=>{
281+
constdata=[];
282+
constclient=newSockJS(`http://localhost:${port}/sockjs-node`);
283+
284+
client.onopen=()=>{
285+
data.push('open');
286+
};
287+
288+
client.onmessage=(e)=>{
289+
data.push(e.data);
290+
};
291+
292+
client.onclose=()=>{
293+
data.push('close');
294+
};
295+
296+
setTimeout(()=>{
297+
expect(data).toMatchSnapshot();
298+
constcalls=mockWarn.mock.calls;
299+
mockWarn.mockRestore();
300+
301+
letfoundWarning=false;
302+
constregExp=/serverModeimplementationmustpassheaderstothecallbackofonConnection\(f\)/;
303+
calls.every((call)=>{
304+
if(regExp.test(call)){
305+
foundWarning=true;
306+
returnfalse;
307+
}
308+
returntrue;
309+
});
310+
311+
expect(foundWarning).toBeTruthy();
312+
313+
done();
314+
},5000);
315+
});
316+
});
226317
});

0 commit comments

Comments
 (0)