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

Cannot set cookies with domain localhost #215

Closed
lfdebrux opened this issue Jul 27, 2021 · 10 comments · Fixed by #221
Closed

Cannot set cookies with domain localhost #215

lfdebrux opened this issue Jul 27, 2021 · 10 comments · Fixed by #221
Assignees

Comments

@lfdebrux
Copy link

lfdebrux commented Jul 27, 2021

When using option rejectPublicSuffixes: true (the default), trying to set a cookie with Domain=localhost throws the error Cookie has domain set to a public suffix, which I believe is incorrect.

How to reproduce

Run the following code with the latest master of tough-cookie (commit 1b25269)

const { CookieJar } = require("../lib/cookie");
const cookieJar = new CookieJar();
cookieJar.setCookieSync("a=b; Domain=localhost", "http://localhost")  // throws 'Error: Cookie has domain set to a public suffix'

Expected result

I can set cookies with Domain=localhost without an error.

Workaround

Turning off the rejectPublicSuffixes option when creating the CookieJar causes the cookie to be set without errors, as expected.

@lfdebrux lfdebrux changed the title Bug prevents setting cookies with domain=localhost Bug prevents setting cookies with domain localhost Jul 27, 2021
@lfdebrux lfdebrux changed the title Bug prevents setting cookies with domain localhost Cannot set cookies with domain localhost Jul 27, 2021
vanitabarrett pushed a commit to alphagov/govuk-design-system that referenced this issue Jul 28, 2021
Without this config, the default URL is 'localhost' which causes
some issues when setting cookies because of a bug in tough-cookie which treats
localhost like a public domain. Because you can't set cookies on a public domain,
cookies were not being set in the tests.

Setting the testURL to a real URL fixes this issue.

@lfdebrux has raised an issue with tough-cookie here: salesforce/tough-cookie#215
vanitabarrett pushed a commit to alphagov/govuk-design-system that referenced this issue Aug 11, 2021
Without this config, the default URL is 'localhost' which causes
some issues when setting cookies because of a bug in tough-cookie which treats
localhost like a public domain. Because you can't set cookies on a public domain,
cookies were not being set in the tests.

Setting the testURL to a real URL fixes this issue.

@lfdebrux has raised an issue with tough-cookie here: salesforce/tough-cookie#215
@awaterma
Copy link
Member

We're not seeing localhost on the main suffix list: https://publicsuffix.org/list/public_suffix_list.dat

However, localhost is a special case domain: https://datatracker.ietf.org/doc/rfc6761/

We are thinking of just updating the error in this case; but I'll let @ruoho-sfdc comment further.

@medelibero-sfdc
Copy link
Contributor

Hi @lfdebrux,

I just tried to recreate this issue with the following code but I was not able to.

const jar = new tough.CookieJar(); jar.setCookieSync("a=b; Domain=localhost", "http://localhost")

What am I doing wrong? It looks like the same code? If you try this against the master branch are you able to reproduce the problem?

Thanks,
Mike

@lfdebrux
Copy link
Author

Hi @medelibero-sfdc,

I'm not sure why your setup isn't raising the error... if I checkout the current version of the master branch and run your snippet I do get the error 🤔

tough-cookie at 09:15:09 
% node -e 'const tough = require("."); const jar = new tough.CookieJar(); jar.setCookieSync("a=b; Domain=localhost", "http://localhost")'
/Users/laurencedebruxelles/Code/tough-cookie/lib/cookie.js:1714
      throw syncErr;
      ^

Error: Cookie has domain set to a public suffix
    at CookieJar.setCookie (/Users/laurencedebruxelles/Code/tough-cookie/lib/cookie.js:1172:15)
    at CookieJar.setCookie (/Users/laurencedebruxelles/Code/tough-cookie/node_modules/universalify/index.js:5:67)
    at CookieJar.setCookieSync (/Users/laurencedebruxelles/Code/tough-cookie/lib/cookie.js:1708:21)
    at [eval]:1:68
    at Script.runInThisContext (vm.js:134:12)
    at Object.runInThisContext (vm.js:310:38)
    at internal/process/execution.js:81:19
    at [eval]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_string.js:27:3

@awaterma
Copy link
Member

@ifdebrux -- could you also kindly let us know what version of NodeJS you are testing with?

@lfdebrux
Copy link
Author

@awaterma I tested with Node 12 (v12.22.6), Node 14 (v14.17.6), and Node 16 (v16.11.0). All versions produced the same error.

@awaterma
Copy link
Member

@ifdebrux -- I can reproduce this now in a vows unit test. I'll look into the issue a bit further and see if I can propose a fix.

.addBatch({
    "setCookie with localhost (GH-215)": {
      topic: function() {
        const cookieJar = new CookieJar();
        return cookieJar.setCookieSync("a=b; Domain=localhost", "http://localhost")  // should throw 'Error: Cookie has domain set to a public suffix'
      },
      works: function(c) {
        assert.instanceOf(c, Cookie)
      }
    }
  })

Result:

setCookie with localhost (GH-215) 
      ✗ works 
        » An unexpected error was caught: Error: Cookie has domain set to a public suffix 
      at CookieJar.setCookie (/home/cookie/lib/cookie.js:1172:15) 
      at CookieJar.setCookie (/home/cookie/node_modules/universalify/index.js:5:67) 
      at CookieJar.setCookieSync (/home/cookie/lib/cookie.js:1708:21) 
      at Object.topic (/home/cookie/test/regression_test.js:195:26) 
      at run (/home/cookie/node_modules/vows/lib/vows/suite.js:133:35) 
      ....

@awaterma
Copy link
Member

I've looked into the RFCs for this; and I think our current behavior is acceptable. localhost is a special domain, but its behavior in cookies, as a site domain, doesn't seem well defined, as far as I can tell. Please see: https://datatracker.ietf.org/doc/html/rfc6761#section-6.3 and https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3. In our case, we do allow ".localhost" as a special domain, per 6761, but choose to treat "localhost" as a Public Suffix. You can work around this in several ways, as the following tests show:

.addBatch({
    "setCookie with localhost (GH-215)": {
      topic: function() {
        const cookieJar = new CookieJar();
        return cookieJar.setCookieSync("a=b; Domain=", "http://localhost")  // when domain set to 'localhost', will throw 'Error: Cookie has domain set to a public suffix'
      },
      works: function(c) {
        assert.instanceOf(c, Cookie)
      }
    }},
    { 
      "setCookie with localhost (localhost.local domain)": {
        topic: function() {
        const cookieJar = new CookieJar();
        return cookieJar.setCookieSync("a=b; Domain=localhost.local", "http://localhost")
      },
      works: function(c) {
        assert.instanceOf(c, Cookie)
      }
    }},
    { 
      "setCookie with localhost (.localhost domain)": {
        topic: function() {
        const cookieJar = new CookieJar();
        return cookieJar.setCookieSync("a=b; Domain=.localhost", "http://localhost")
      },
      works: function(c) {
        assert.instanceOf(c, Cookie)
      }
    }
  })

There is also some discussion on the following thread, which also speaks to how several browsers handle the issue: https://stackoverflow.com/questions/1134290/cookies-on-localhost-with-explicit-domain

And there are similar issues filed with other cookie based projects, for example:

I'll use this work item to check in the test updates; so you and others at least have a direction to go with local cookie development.

If you can build an argument from the RFCs that show that we have taken the wrong approach; we'll gladly reconsider!

Pull requests and accompanying tests really help us move along issues! Please take a look at the sample above, discussion links and let us know your thoughts.

@awaterma
Copy link
Member

@miggs125 helped us with our implementation in issue #160, for special use domains. He may have some thoughts to contribute to this thread.

@lfdebrux
Copy link
Author

Hi @awaterma, thanks for the detailed investigation! I guess I'm not so bothered by the correctness of what tough-cookie does, it's more about the fact that it is surprising, and it took me a long time when I initially hit this issue to figure out what was going on. I guess it's possible I'm the only one who was confused by the error message, but I think like you said tweaking the error message might be helpful. Or maybe just adding something to the docs for the rejectPublicSuffixes option to make it explicit that localhost is considered a public suffix.

@awaterma
Copy link
Member

That's a great suggestion @lfdebrux. I'll see if I can make a better error message, or update the docs a bit to make this behavior more clear for others. :)

4.01/4.1 Release Plan automation moved this from In progress to Done Oct 25, 2021
ruoho-sfdc added a commit that referenced this issue Oct 25, 2021
@GH-215 -- Tests that document localhost behavior when set as domain.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

4 participants