Skip to content

CORS headers issue: origins filter still get ignored when emitting "Transport unknown" error #3415

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

Closed
fedulovivan opened this issue Mar 4, 2019 · 4 comments

Comments

@fedulovivan
Copy link

fedulovivan commented Mar 4, 2019

Found that CORS header Access-Control-Allow-Origin is still generated for any Origin ignoring origins filter.

This is related to already reported and closed issues #449, #331, #2850 and pr #452

Steps to reproduce (here is full commit with reproduction scenario in my app):

  1. Create server instance and restrict origins as:
const io = SocketIo(server, { origins: 'http://localhost:8888' });
  1. Use curl and send GET request (note the terminating slash):
curl -GET -H "Origin: http://wertwertffff.com" --verbose http://localhost:8888/socket.io/

Expected behavior:
403 HTTP code and corresponding error is generated, no Access-Control-Allow-* headers are present in response.

Actual result:

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8888 (#0)
> GET /socket.io/ HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.47.0
> Accept: */*
> Origin: http://wertwertffff.com
> 
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: http://wertwertffff.com
< Date: Mon, 04 Mar 2019 16:06:20 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
{"code":0,"message":"Transport unknown"}

Moreover, such behavior also causes security scanner (was tested with Burp Suite) to report websockets url as faulty.

@fedulovivan
Copy link
Author

The workaround is following monkey-patch:

import engineio from 'engine.io';
const debug = require('debug')('engine');
const originalVerify = engineio.Server.prototype.verify;
engineio.Server.prototype.verify = function(req, upgrade, fn, ...rest) {
    const transport = get(req, '_query.transport');
    let error = false;
    if (!transport) {
        debug(`patched 'verify' method is invoked. req._query.transport is empty: emitting FORBIDDEN error`);
        error = true;
    } else if (this.transports.indexOf(transport) === -1) {
        debug(`patched 'verify' method is invoked. req._query.transport=${transport} is unknown: emitting FORBIDDEN error`);
        error = true;
    }
    if (error) {
        // FORBIDDEN code will be eventually handled by Server::sendErrorMessage
        // and response won't be populated with 'Access-Control-Allow-*' headers
        return fn(engineio.Server.FORBIDDEN, false);
    }
    return originalVerify.call(this, req, upgrade, fn, ...rest);
};

@mrfambo
Copy link

mrfambo commented Mar 12, 2019

This is extremely annoying, i am trying to debug the issue from past 16 Hours and still getting the same Cross Origin Issue.
I have my server running on App Engine, i am trying to connect my React App, deployed outside app-engine with the server(on app engine) and it is giving me CORS issue.

Access to XMLHttpRequest at 'https://MYAPPENGINEID.appspot.com/socket.io/?EIO=3&transport=polling&t=MbmyzvQ' from origin 'https://MYREACTAPP.com' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

The problem is pretty straight forward, it must not respond with a wild card entry in response, rather it should match with the request headers so that i may not get issues with it.

Extremely annoying and pathetic problem, trying all my ups and downs to get it resolved but i couldn't. All the resources on Web are not solving the issue.

@icebob
Copy link

icebob commented Jul 23, 2019

Same issue is here. Will be fixed it?

I think we should move the CORS part to the top of the function here in engine.io:

function sendErrorMessage (req, res, code) {
  var headers = { 'Content-Type': 'application/json' };

  var isForbidden = !Server.errorMessages.hasOwnProperty(code);
  if (isForbidden) {
    res.writeHead(403, headers);
    res.end(JSON.stringify({
      code: Server.errors.FORBIDDEN,
      message: code || Server.errorMessages[Server.errors.FORBIDDEN]
    }));
    return;
  }
  if (req.headers.origin) {
    headers['Access-Control-Allow-Credentials'] = 'true';
    headers['Access-Control-Allow-Origin'] = req.headers.origin;
  } else {
    headers['Access-Control-Allow-Origin'] = '*';
  }
  if (res !== undefined) {
    res.writeHead(400, headers);
    res.end(JSON.stringify({
      code: code,
      message: Server.errorMessages[code]
    }));
  }
}

@darrachequesne
Copy link
Member

For future readers: the origins method was removed in Socket.IO v3

Documentation:

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

No branches or pull requests

4 participants