-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make origins
option more flexible and similar to later versions of socket.io
#12
base: 0.9.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,6 @@ exports = module.exports = Manager; | |
|
||
var defaultTransports = exports.defaultTransports = [ | ||
'websocket' | ||
, 'htmlfile' | ||
, 'xhr-polling' | ||
, 'jsonp-polling' | ||
]; | ||
|
@@ -60,7 +59,7 @@ function Manager (server, options) { | |
this.namespaces = {}; | ||
this.sockets = this.of(''); | ||
this.settings = { | ||
origins: '*:*' | ||
origins: [] | ||
, log: true | ||
, store: new MemoryStore | ||
, logger: new Logger | ||
|
@@ -76,8 +75,6 @@ function Manager (server, options) { | |
, 'heartbeat interval': 25 | ||
, 'heartbeat timeout': 60 | ||
, 'polling duration': 20 | ||
, 'flash policy server': true | ||
, 'flash policy port': 10843 | ||
, 'destroy upgrade': true | ||
, 'destroy buffer size': 10E7 | ||
, 'browser client': true | ||
|
@@ -873,40 +870,45 @@ Manager.prototype.handshakeData = function (data, connection) { | |
}; | ||
}; | ||
|
||
function isString(s) { | ||
return typeof s === 'string' || s instanceof String; | ||
} | ||
|
||
// Adapted from Express's CORS module | ||
// (https://github.com/expressjs/cors/blob/1cfb3709dec33dfa7ae95a3a554f2dd10498c7f9/lib/index.js) | ||
Manager.prototype.isOriginAllowed = function (origin) { | ||
var allowedOrigin = this.get('origins'); | ||
if (typeof allowedOrigin === 'function') { | ||
return allowedOrigin(origin); | ||
} else if (Array.isArray(allowedOrigin)) { | ||
for (var i = 0; i < allowedOrigin.length; ++i) { | ||
if (this.isOriginAllowed(origin, allowedOrigin[i])) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} else if (isString(allowedOrigin)) { | ||
return allowedOrigin === '*' || origin === allowedOrigin; | ||
} else if (allowedOrigin instanceof RegExp) { | ||
return allowedOrigin.test(origin); | ||
} else { | ||
return !!allowedOrigin; | ||
} | ||
}; | ||
|
||
/** | ||
* Verifies the origin of a request. | ||
* | ||
* @api private | ||
*/ | ||
|
||
Manager.prototype.verifyOrigin = function (request) { | ||
var origin = request.headers.origin || request.headers.referer | ||
, origins = this.get('origins'); | ||
|
||
if (origin === 'null') origin = '*'; | ||
|
||
if (origins.indexOf('*:*') !== -1) { | ||
return true; | ||
var origin = request.headers.origin || request.headers.referer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original code did a bit of normalisation on the origin to fix differences between an origin and a referer. We can account for this by using a function in real-time so it doesn't need to change - just noting it as a difference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed. I alluded to that in the description, although maybe slightly obliquely. |
||
var allowed = this.isOriginAllowed(origin); | ||
if (!origin && !allowed) { | ||
this.log.warn('origin missing from handshake, yet required by config', { headers: request.headers }); | ||
} | ||
|
||
if (origin) { | ||
try { | ||
var parts = url.parse(origin); | ||
parts.port = parts.port || 80; | ||
var ok = | ||
~origins.indexOf(parts.hostname + ':' + parts.port) || | ||
~origins.indexOf(parts.hostname + ':*') || | ||
~origins.indexOf('*:' + parts.port); | ||
if (!ok) this.log.warn('illegal origin: ' + origin); | ||
return ok; | ||
} catch (ex) { | ||
this.log.warn('error parsing origin'); | ||
} | ||
} | ||
else { | ||
this.log.warn('origin missing from handshake, yet required by config'); | ||
} | ||
return false; | ||
return allowed; | ||
}; | ||
|
||
/** | ||
|
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this mean that the default empty array will block access?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is similar to what recent versions of socket.io do: https://socket.io/docs/v4/handling-cors/#configuration. Do you think it's a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that by default CORS is disabled in the current version of socket.io so a request from overleaf.com -> overleaf.com would succeed with a default configuration (see this example of same origin with no CORS). This code will fail regardless of origin (even same origin requests will fail because it is impossible for anything to pass the default setup).
I think the original report would be addressed by just not sending the
Access-Control-Allow-Origin
header and disallowing requests with an explicitOrigin
but I think that websockets don't have to obey Same Site rules so we'd be potentially vulnerable and might well get another report for the upgraded endpoint.It's possible to work around this API design in real-time by passing a wildcard rule if we don't configure anything (otherwise we will have a breaking change in CE and Server Pro) but the API feels weird to me to be unable to serve requests by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, that's a good point. I already feel as though I've changed too much code here. I'll have a little think.