feat: Add RFC 6761–compliant localhost loopback checks so `secure` cookies work on localhost (fixes: #1676)
fixes: #1676
Jira: https://usebruno.atlassian.net/browse/BRU-859
Description
Contribution Checklist:
- [x] The pull request only addresses one issue or adds one feature.
- [x] The pull request does not introduce any breaking changes
- [x] I have added screenshots or gifs to help explain the change if applicable.
- [x] I have read the contribution guidelines.
- [x] Create an issue and link to the pull request.
This commit extends how cookies are treated in secure contexts by fully recognizing localhost and loopback IPs as trustworthy origins, matching the de facto behavior of all modern browsers and RFC 6761. Previously, tough-cookie defaulted secure to true only for https: and wss: URLs, causing cookies with secure set to never be sent to localhost.
What Changed
-
New
trustworthy-util.js- Implements
isPotentiallyTrustworthy(url)by checking:- Schemes:
https,wss,file - Loopback IPs:
127.0.0.1/8and::1 - Hostnames:
localhostand*.localhost
- Schemes:
- Adapted from Chromium’s
IsLocalhost,IsLoopbackandHostNoBracketsPiece, located at:
- Implements
-
cookies.jsUpdate- Passes the
{ secure: isPotentiallyTrustworthy(url) }option tocookieJar.getCookiesSync(). - This overrides
tough-cookie’s built-in:
We do everythinglet secure = options.secure; if (secure == null && (context.protocol == "https:" || context.protocol == "wss:")) { secure = true; }tough-cookiedoes by default—plus treat localhost/loopback the same as modern browsers. No existing functionality is removed, only expanded.
- Passes the
Testing this change
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route('/setcookie')
def set_cookie():
resp = make_response('')
resp.set_cookie('example', '', secure=True)
return resp
@app.route('/getcookie')
def get_cookie():
return 'Cookie is set' if 'example' in request.cookies else 'No cookie set'
app.run()
- Before: The
securecookie would not be sent to/getcookieafter it was set by/setcookiedue tosecurebeing set toTrue. - After: The
securecookie would be sent to/getcookiewhich mirrors the behavior of modern browsers.
All modern browsers (Chrome et al.) and many other API testing clients (Postman et al.) handle http://localhost as a trustworthy origin. It only makes sense that this behavior also exists in Bruno.
@sreelakshmi-bruno - Any chancel to get this merged in?
This will be merged and will be included in the upcoming release which will likely go out on coming Tuesday.
Apologies, we've postponed the release for this PR to April. Thank you for your patience!
@Chriss4123 I see that your PR on salesforce/tough-cookie is already merged. That alone is great news and thanks for your contributions.
Do you think we can just get straight to upgrading tough-cookie once their major release is out?
@Chriss4123 I see that your PR on
salesforce/tough-cookieis already merged. That alone is great news and thanks for your contributions.Do you think we can just get straight to upgrading
tough-cookieonce their major release is out?
Yes, that should work. Just keep in mind tough-cookie has been converted to TypeScript a while ago, however you are using an old version which still uses vanilla JS.
Since tough-cookie v6 is still in RC, I think we can go ahead with merging this for now.
I'm also adding few tests for this in #4709. Will add a note as well regarding upgrading it.
Moved the util to @usebruno/common and fixed it for CLI as well.
@ramki-bruno I'd like to keep the bruno-common platform agnostic as it gets bundled. Can you move the logic to bruno-requests ?
Please use Merge commit