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

Add secure cookies when remote is localhost #858

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

thegoldgoat
Copy link

See #857

This PR enables secure cookies to be transmitted when the remoteAddress is localhost (both IPv4 & IPv6)

I also updated the README to match the new behavior, but I need help writing the tests: the one marked 'TODO' currently fails, we would need to create a couple of tests for both localhost connection and non-localhost one.

@thegoldgoat thegoldgoat marked this pull request as draft December 22, 2021 12:28
@thegoldgoat
Copy link
Author

Still needs to update tests, marked as draft.

index.js Outdated
Comment on lines 626 to 628
if (req.connection.remoteAddress === '127.0.0.1' ||
req.connection.remoteAddress === '::ffff:127.0.0.1'
) {
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 condition be true for most reverse proxy setups? Or does Express mutate req.connection.remoteAddress if trust proxy is enabled? (The documentation is not clear.)

Copy link
Contributor

Choose a reason for hiding this comment

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

You are correct. I don't think this will work correctly as any reverse proxy on localhost (think typicall ssl ofloading or even just kubernetes side cars) would end up as thinking this is a localhost connection. Express does not alter any values that are provided from Node.js HTTP core.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah I see, I think the reasonable way to do this is to check if we are behind a proxy

index.js Outdated

// socket is localhost
if (req.connection.remoteAddress === '127.0.0.1' ||
req.connection.remoteAddress === '::ffff:127.0.0.1'
Copy link

Choose a reason for hiding this comment

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

What about IPv6 localhost?

Suggested change
req.connection.remoteAddress === '::ffff:127.0.0.1'
req.connection.remoteAddress === '::ffff:127.0.0.1' ||
req.connection.remoteAddress === '::1'

Copy link
Author

Choose a reason for hiding this comment

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

Oh, I forgot about that you are right!

README.md Outdated
have your node.js behind a proxy and are using `secure: true`, you need to set
"trust proxy" in express:
an https-enabled website (or connection via localhost), i.e., HTTPS is necessary
for secure cookies. If `secure` is set, and you access your site over HTTP, the
Copy link
Contributor

Choose a reason for hiding this comment

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

HTTPS is necessary
for secure cookies

Probably this line would need reworded with a change like this, as I believe that is the whole point of this change, that HTTP would work for localhost.

Copy link
Author

Choose a reason for hiding this comment

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

Take a look at 8314c37, I think it is clear that way

}

// proxy not explicitly trusted; no proxy means connection is secure
if (req.headers['x-forwarded-proto'] !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately this is also not a reliable test, because if the user does not trust the connection as a proxy, this header may not be set if not a proxy or may be forgable by the client.

Copy link
Author

Choose a reason for hiding this comment

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

Sorry I am not sure what you mean, maybe I am missing some possible network configuration?

Since we detect a localhost connection we could trust the remote (reverse proxy or client) right?

Please correct me if I am wrong

Copy link
Contributor

Choose a reason for hiding this comment

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

Not unless the user of this module specifies they trust it. This fixed a reported security vulnerability.

Copy link
Author

Choose a reason for hiding this comment

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

Oh I see what you mean, so we can conclude that the only thing we can do is return true if the proxy is trusted and the connection is localhost, right?


- https-enabled website
- localhost connection
- node.js behind a proxy and "trust proxy" in express
Copy link
Contributor

Choose a reason for hiding this comment

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

It wouldn't just be behind trust proxy, as you can still have a http connection though a proxy.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah my bad, does node.js behind an HTTPS proxy and "trust proxy" in express sound good?
I also need to update the localhost one, specifying that "trust proxy" is also needed

@thegoldgoat
Copy link
Author

This has been stale for a while...

Oh I see what you mean, so we can conclude that the only thing we can do is return true if the proxy is trusted and the connection is localhost, right?

So, are you ok with this one? Otherwise I would have no other idea and we can close this..

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

Successfully merging this pull request may close these issues.

None yet

3 participants