Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: socketio/socket.io
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 47161a65d40c2587535de750ac4c7d448e5842ba
Choose a base ref
...
head repository: socketio/socket.io
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 873fdc55eddd672960fdbc1325ccb7c4bf466f05
Choose a head ref
  • 5 commits
  • 9 files changed
  • 2 contributors

Commits on Jan 4, 2021

  1. ci: migrate to GitHub Actions

    Due to the recent changes to the Travis CI platform (see [1]), we will
    now use GitHub Actions to run the tests.
    
    Reference: https://docs.github.com/en/free-pro-team@latest/actions/guides/building-and-testing-nodejs
    
    [1]: https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing
    darrachequesne committed Jan 4, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    minborg Per-Ake Minborg
    Copy the full SHA
    6fa026f View commit details
  2. Copy the full SHA
    3951a79 View commit details
  3. fix: properly overwrite the query sent in the handshake

    The `query` option of the Manager had the priority over the one of the
    Socket instance, which meant updating the Socket#query object on the
    client-side was not reflected in the Socket#handshake object on the
    server-side.
    
    Please note that the behavior of the `query` option is still a bit
    weird in Socket.IO v2, as it only applies to non-default namespace.
    This is fixed in v3:
    
    - https://socket.io/docs/v3/migrating-from-2-x-to-3-0/#Add-a-clear-distinction-between-the-Manager-query-option-and-the-Socket-query-option
    - https://socket.io/docs/v3/middlewares/#Sending-credentials
    
    Fixes #3495
    sebamarynissen authored and darrachequesne committed Jan 4, 2021
    Copy the full SHA
    d33a619 View commit details
  4. fix(security): do not allow all origins by default

    BREAKING CHANGE: previously, all origins were allowed by default, which
    meant that a Socket.IO server sent the necessary CORS headers
    (`Access-Control-Allow-xxx`) to any domain by default.
    
    Please note that you are not impacted if:
    
    - you are using Socket.IO v2 and the `origins` option to restrict the list of allowed domains
    - you are using Socket.IO v3 (disabled by default)
    
    This commit also removes the support for '*' matchers and protocol-less
    URL:
    
    ```
    io.origins('https://example.com:443'); => io.origins(['https://example.com']);
    io.origins('localhost:3000');          => io.origins(['http://localhost:3000']);
    io.origins('http://localhost:*');      => io.origins(['http://localhost:3000']);
    io.origins('*:3000');                  => io.origins(['http://localhost:3000']);
    ```
    
    To restore the previous behavior (please use with caution):
    
    ```js
    io.origins((_, callback) => {
      callback(null, true);
    });
    ```
    
    See also:
    
    - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    - https://socket.io/docs/v3/handling-cors/
    - https://socket.io/docs/v3/migrating-from-2-x-to-3-0/#CORS-handling
    
    Thanks a lot to https://github.com/ni8walk3r for the security report.
    darrachequesne committed Jan 4, 2021
    1
    Copy the full SHA
    f78a575 View commit details
  5. chore(release): 2.4.0

    darrachequesne committed Jan 4, 2021
    Copy the full SHA
    873fdc5 View commit details
Showing with 3,428 additions and 64 deletions.
  1. +24 −0 .github/workflows/ci.yml
  2. +0 −12 .travis.yml
  3. +7 −0 CHANGELOG.md
  4. +1 −1 Readme.md
  5. +10 −23 lib/index.js
  6. +1 −1 lib/socket.js
  7. +3,352 −0 package-lock.json
  8. +3 −3 package.json
  9. +30 −24 test/socket.io.js
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI

on:
push:
pull_request:

jobs:
test-node:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x, 14.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
env:
CI: true
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# [2.4.0](https://github.com/socketio/socket.io/compare/2.3.0...2.4.0) (2021-01-04)


### Bug Fixes

* **security:** do not allow all origins by default ([f78a575](https://github.com/socketio/socket.io/commit/f78a575f66ab693c3ea96ea88429ddb1a44c86c7))
* properly overwrite the query sent in the handshake ([d33a619](https://github.com/socketio/socket.io/commit/d33a619905a4905c153d4fec337c74da5b533a9e))
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
# socket.io

[![Backers on Open Collective](https://opencollective.com/socketio/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/socketio/sponsors/badge.svg)](#sponsors)
[![Build Status](https://secure.travis-ci.org/socketio/socket.io.svg?branch=master)](https://travis-ci.org/socketio/socket.io)
[![Build Status](https://github.com/socketio/socket.io/workflows/CI/badge.svg)](https://github.com/socketio/socket.io/actions)
[![Dependency Status](https://david-dm.org/socketio/socket.io.svg)](https://david-dm.org/socketio/socket.io)
[![devDependency Status](https://david-dm.org/socketio/socket.io/dev-status.svg)](https://david-dm.org/socketio/socket.io#info=devDependencies)
[![NPM version](https://badge.fury.io/js/socket.io.svg)](https://www.npmjs.com/package/socket.io)
33 changes: 10 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ function Server(srv, opts){
this.parser = opts.parser || parser;
this.encoder = new this.parser.Encoder();
this.adapter(opts.adapter || Adapter);
this.origins(opts.origins || '*:*');
this.origins(opts.origins || []);
this.sockets = this.of('/');
if (srv) this.attach(srv, opts);
}
@@ -67,31 +67,18 @@ function Server(srv, opts){
*/

Server.prototype.checkRequest = function(req, fn) {
var origin = req.headers.origin || req.headers.referer;
const origin = req.headers.origin;

// file:// URLs produce a null Origin which can't be authorized via echo-back
if ('null' == origin || null == origin) origin = '*';
if (typeof this._origins === 'function') {
return this._origins(origin, fn);
}

if (!!origin && typeof(this._origins) == 'function') return this._origins(origin, fn);
if (this._origins.indexOf('*:*') !== -1) return fn(null, true);
if (origin) {
try {
var parts = url.parse(origin);
var defaultPort = 'https:' == parts.protocol ? 443 : 80;
parts.port = parts.port != null
? parts.port
: defaultPort;
var ok =
~this._origins.indexOf(parts.protocol + '//' + parts.hostname + ':' + parts.port) ||
~this._origins.indexOf(parts.hostname + ':' + parts.port) ||
~this._origins.indexOf(parts.hostname + ':*') ||
~this._origins.indexOf('*:' + parts.port);
debug('origin %s is %svalid', origin, !!ok ? '' : 'not ');
return fn(null, !!ok);
} catch (ex) {
}
fn(null, this._origins.includes(origin));
} else {
const noOriginIsValid = this._origins.length === 0;
fn(null, noOriginIsValid);
}
fn(null, false);
};

/**
@@ -237,7 +224,7 @@ Server.prototype.adapter = function(v){
Server.prototype.origins = function(v){
if (!arguments.length) return this._origins;

this._origins = v;
this._origins = typeof v === 'string' ? [v] : v;
return this;
};

2 changes: 1 addition & 1 deletion lib/socket.js
Original file line number Diff line number Diff line change
@@ -116,7 +116,7 @@ Socket.prototype.buildHandshake = function(query){
function buildQuery(){
var requestQuery = url.parse(self.request.url, true).query;
//if socket-specific query exist, replace query strings in requestQuery
return Object.assign({}, query, requestQuery);
return Object.assign({}, requestQuery, query);
}
return {
headers: this.request.headers,
3,352 changes: 3,352 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "socket.io",
"version": "2.3.0",
"version": "2.4.0",
"description": "node.js realtime framework server",
"keywords": [
"realtime",
@@ -25,10 +25,10 @@
},
"dependencies": {
"debug": "~4.1.0",
"engine.io": "~3.4.0",
"engine.io": "~3.5.0",
"has-binary2": "~1.0.2",
"socket.io-adapter": "~1.1.0",
"socket.io-client": "2.3.0",
"socket.io-client": "2.4.0",
"socket.io-parser": "~3.4.0"
},
"devDependencies": {
54 changes: 30 additions & 24 deletions test/socket.io.js
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ describe('socket.io', function(){
it('should be able to set origins to engine.io', function() {
var srv = io(http());
srv.set('origins', 'http://hostname.com:*');
expect(srv.origins()).to.be('http://hostname.com:*');
expect(srv.origins()).to.eql(['http://hostname.com:*']);
});

it('should be able to set authorization and send error packet', function(done) {
@@ -262,17 +262,6 @@ describe('socket.io', function(){
});
});

it('should allow request when origin defined an the same is specified', function(done) {
var sockets = io({ origins: 'http://foo.example:*' }).listen('54015');
request.get('http://localhost:54015/socket.io/default/')
.set('origin', 'http://foo.example')
.query({ transport: 'polling' })
.end(function (err, res) {
expect(res.status).to.be(200);
done();
});
});

it('should allow request when origin defined as function and same is supplied', function(done) {
var sockets = io({ origins: function(origin,callback){
if (origin == 'http://foo.example') {
@@ -307,7 +296,7 @@ describe('socket.io', function(){

it('should allow request when origin defined as function and no origin is supplied', function(done) {
var sockets = io({ origins: function(origin,callback){
if (origin == '*') {
if (origin === undefined) {
return callback(null, true);
}
return callback(null, false);
@@ -320,17 +309,6 @@ describe('socket.io', function(){
});
});

it('should default to port 443 when protocol is https', function(done) {
var sockets = io({ origins: 'https://foo.example:443' }).listen('54036');
request.get('http://localhost:54036/socket.io/default/')
.set('origin', 'https://foo.example')
.query({ transport: 'polling' })
.end(function (err, res) {
expect(res.status).to.be(200);
done();
});
});

it('should allow request if custom function in opts.allowRequest returns true', function(done){
var sockets = io(http().listen(54022), { allowRequest: function (req, callback) {
return callback(null, true);
@@ -367,6 +345,17 @@ describe('socket.io', function(){
done();
});
});

it('should disallow any origin by default', (done) => {
io().listen('54025');
request.get('http://localhost:54025/socket.io/default/')
.set('origin', 'https://foo.example')
.query({ transport: 'polling' })
.end((err, res) => {
expect(res.status).to.be(403);
done();
});
});
});

describe('close', function(){
@@ -1621,8 +1610,25 @@ describe('socket.io', function(){
expect(s.handshake.query.key2).to.be('&=bb');
done();
});
});

it('should see the query options sent in the Socket.IO handshake (specific to the given socket)', (done) => {
const srv = http();
const sio = io(srv);
const socket = client(srv, '/namespace',{ query: { key1: 'a', key2: 'b' }}); // manager-specific query option
socket.query = { key2: 'c' }; // socket-specific query option

const success = () => {
sio.close();
socket.close();
done();
}

sio.of('/namespace').on('connection', (s) => {
expect(s.handshake.query.key1).to.be('a'); // in the query params
expect(s.handshake.query.key2).to.be('c'); // in the Socket.IO handshake
success();
});
});

it('should handle very large json', function(done){