Skip to content
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

Open
wants to merge 3 commits into
base: 0.9.x
Choose a base branch
from

Conversation

timdown
Copy link

@timdown timdown commented Jan 24, 2025

This is to support custom origin checking in the Overleaf real-time service.

Changes:

  • Overhaul origins option to allow a regex, function, string or boolean, or an array of any mix of these
  • Change origins option default to disallow any origin
  • Remove htmlfile transport
  • Remove flashsocket transport

This still falls back to checking the referrer header when origin is missing. This is a questionable practice and modern versions of socket.io don't do this. The referrer header also has the path, unlike the origin, which means we have to handle that in the origins option, probably using a regex. I couldn't see an easy way round it though because our pre-flight requests have no origin header, and I'm guessing we'd need to update our fork of socket.io-client to fix that, which seemed too risky to me.

@timdown timdown requested a review from Seinzu January 24, 2025 13:09
lib/manager.js Outdated Show resolved Hide resolved
@timdown timdown force-pushed the td-origins-setting branch 5 times, most recently from 1d6488a to 1c0aa2f Compare January 31, 2025 17:34
@timdown timdown force-pushed the td-origins-setting branch from 1c0aa2f to 0904bb6 Compare January 31, 2025 17:43
@timdown timdown requested a review from Seinzu February 7, 2025 10:00
@timdown timdown changed the title Add support for supplying a function for origins to allow more sensible origin verification Make origins option more flexible and similar to later versions of socket.io Feb 7, 2025
return true;
}
}
return false;
Copy link

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?

Copy link
Author

@timdown timdown Feb 7, 2025

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?

Copy link

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 explicit Origin 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.

Copy link
Author

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).

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.


if (origins.indexOf('*:*') !== -1) {
return true;
var origin = request.headers.origin || request.headers.referer;
Copy link

@Seinzu Seinzu Feb 7, 2025

Choose a reason for hiding this comment

The 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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I alluded to that in the description, although maybe slightly obliquely.

Copy link

@Seinzu Seinzu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to fix the default case before we can go ahead. The rest of it looks good.

@Seinzu Seinzu assigned timdown and unassigned Seinzu Feb 7, 2025
@Seinzu
Copy link

Seinzu commented Feb 7, 2025

I'm not a big fan of the way the default setup works but it doesn't seem to be blocking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants