-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(pg-connection-string): get closer to libpq semantics for sslmode
#2709
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
Conversation
@charmander do we have an idea when this will land / get released as part of pg9? |
Help @brianc to merge this |
@brianc / @hjr3 what's the status on this? We've a PR on Mastodon blocked by this change: mastodon/mastodon#25483 |
@ThisIsMissEm Is that PR blocked on this? It looks more like it would be made unnecessary by this. |
I'm saying "blocked" in the sense of if upstream is going to fix, that'd be preferable to a fix in our code for it |
@ThisIsMissEm On second read, it looks like the Mastodon PR is necessary either way. Unless you were planning on deleting all of that code if this were merged and released soon enough? |
This PR introduces breaking changes. We should probably:
|
@hjr3 that sounds good to me! |
Just wanted to follow up and see if there's any plans for forwards progress on this? |
Over on Mastodon, @ThisIsMissEm asked if I might know some Node.js TLS/SSL people who might be able to review this. I hope I'm not pinging too widely, but I'm certainly interested in trying to unblock things for the Mastodon project so....hey, can anyone review? @indutny @jasnell @joyeecheung @tniessen @pimterry @panva @mertcanaltin |
I’m not really up to speed on the Mastodon context here, but some information, if it helps:
|
@charmander |
@ThisIsMissEm In the end it’s up to @brianc, but I’m against supporting Looking back at more of the context and questions, e.g.
(Re: managed database providers: It looks like DigitalOcean, the managed database provider in mastodon/mastodon#11445, is giving bad advice by encouraging people to connect with |
I suggested a path forward here: #2709 (comment) It is not clear to me why we would need to wait until pg 9 to release pg-connection-string v3.0 |
@hjr3 As I mentioned in the same comment:
i.e. we don’t need to wait, but the new major version of pg-connection-string won’t be the default dependency in pg (that it uses to parse |
I somehow missed that. My apologies. I understand and agree with what you are saying. I do think it is fairly common for teams to use newer versions of pg-connection-string with pg. |
In mastodon, we already directly pull in |
I want to continue working on If @brianc can give me merge permissions, I can move the package forward. If there are concerns with my ability to merge other packages, I started #3129 which should allow us to enforce the proper permissions. |
hey sorry I had the flu last week...literally never been that sick before in my life. still only about 80% back to health. Yeah @hjr3 I've "known" you for a long time on github, and trust you. happy to give you merge permissions! You might need to ping me if you need a critical release done to npm at any time, but even though sometimes I go awol for a week or two I am always watching the repo...just hard to do computer stuff when you think you might actually die from the flu! Instead of merging this myself I'm going to give you permissions @hjr3 so we can make sure they work. :) |
f58c6ff
to
0d4289d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as my previous review
since this is part of the monorepo it isn't independently versioned exactly. I need to maintain backwards compatibility with node-postgres as it stands now unless we want to do a major version bump of PG if this is a breaking change....which I'd rather avoid doing. An opt-in flag or some way to turn this on via the connection string would be a nice default behavior for now, and then when I flip to
Yeah any kinda flag you can add to make this an opt-in thing for now would be perfect! 👍 |
note: the tests are failing due to some istambul test coverage metric I never set up myself...feel free to lower the threshold slightly if that's the nudge it needs to get over the finish line. :) |
The more I think about this, the more I am convinced that this should be behind a flag and then we can figure out in the far-term future if we ever want to make this a default. I am very concerned about changing something like All that is to say: no major version upgrade is planned. |
awesome - lmk if you need help gettin' the PR over the finish line! I'm all in favor of not breaking changes! =D
that would be like another, optional, non-"standard" query param in the connection string, yea? |
radical!
…On Thu, Apr 10, 2025 at 12:42 PM Herman J. Radtke III < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In packages/pg-connection-string/index.js
<#2709 (comment)>
:
> case 'no-verify': {
config.ssl.rejectUnauthorized = false
break
}
+ case 'require': {
+ if (config.sslrootcert) {
+ // If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`
+ config.ssl.checkServerIdentity = function () {}
+ } else {
+ config.ssl.rejectUnauthorized = false
+ }
+ break
+ }
+ case 'verify-ca': {
+ config.ssl.checkServerIdentity = function () {}
I think where we are at is:
1. put the check back in place to match libpq semantics
2. improve the error message to warn folks about mitm attacks
3. make the sslmode documentation tradeoffs more clear, especially in
libpq mode
I will send an updated PR soon ™️
—
Reply to this email directly, view it on GitHub
<#2709 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAMHIP5FDGZTA6EQXWKE6L2Y2USHAVCNFSM5O7W67N2U5DIOJSWCZC7NNSXTPCQOVWGYUTFOF2WK43UKJSXM2LFO45TENZVG43TEOJZGM4A>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
case 'verify-ca': | ||
case 'verify-full': { | ||
break | ||
if (config.sslcompat === 'libpq') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than using a value from the connection string, I think it'd be better to have parse
take an option: parse(str: string, useLibpqCompat: boolean)
— that way connection URLs don't have non-standard parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then every application using this library has to implement this out-of-band, right? That's simply not going to happen, so from a user perspective this effectively wouldn't fix the issue of not supporting standard libpq connection strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be an application concern, not a user choice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many libraries that wrap pg
accept a DSN. Those libraries would have to be updated to have whatever function that accepts the DSN also accept this extra parameter.
I don’t know what the best way forward is. It seems like there should be at least a code-side way to set the compatibility flag, as @ThisIsMissEm brought up, if we’re going the route of a compatibility flag? This doesn’t preclude supporting Anyway, my suggestion would be:
Side note: It’s important to fix the pg surprise where the entire |
I have added a the I have created #3421 for the major version upgrade roadmap. I think there are a number of things we want to fix if we do a major version. The desired changes, how we plan and communicate the changes and tracking of those changes will happen in that issue. |
I plan on merging this in a few days unless someone objects. |
Summary
We have found that the handling of the
sslmode
connection string parameter is inconsistent with other PG libraries and with the reference libpq documentation. This PR proposes some changes tosslmode
behavior that are more aligned with libpq.Detailed
sslmode
behaviorHere is the list of all
sslmode
values and their expected behavior with this PR:sslmode=verify-full
Require an SSL connection and verify the CA and server identity.
No changes in this PR.
sslmode=verify-ca
(changed)Require an SSL connection and verify the CA, but not the server identity. This is achieved by setting
ssl.checkServerIdentity
to a no-op function (see docs). Previously, this mode behaved likeverify-full
but that was not consistent with the libpq implementation. SECURITY WARNING: Usingsslmode=verify-ca
requires specifying a CA withsslrootcert
. If a public CA is used,verify-ca
allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks.sslmode=require
(changed)If a root CA is provided via the
sslrootcert
parameter of the connection string, it behaves likeverify-ca
. Otherwise, require an SSL connection but do not verify CA and server identity (ssl.rejectUnauthorized
is set tofalse
).Previously, this mode behaved like
verify-full
but that was not consistent with the libpq implementation.sslmode=no-verify
Require an SSL connection but do not verify CA and server identity (
ssl.rejectUnauthorized
is set tofalse
).No changes in this PR. Note: this mode is not documented in libpq and does not appear to be broadly supported in other libraries, but has been kept as-is for the sake of backwards-compatibility. One option could be to mark it as deprecated since
sslmode=require
could be an alternative, but doing so might have little value for this project.sslmode=prefer
(changed)Require an SSL connection but do not verify CA and server identity (
ssl.rejectUnauthorized
is set tofalse
). Previously, this mode behaved likeverify-full
but that was not consistent with the libpq implementation.In reality, this mode should be even less strict and support a fallback logic from SSL to non-SSL connection if SSL is not accepted by the server. Implementing a fallback logic seems to be more complex to solve and I did not dare touch this, but this could eventually be addressed if users of this library deem this mode valuable.
sslmode=allow
Not supported by this library.
No changes in this PR. For this mode also, there could be an opportunity to implement a fallback logic from non-SSL to SSL, but I did not dare touch this and I don't have data that suggests that this might be valuable for this project.
sslmode=disable
Only try a non-SSL connection.
No changes in this PR
An important note is that this PR potentially introduces semver breaking changes, in particular because it relaxes the security constraints of some
sslmode
values:sslmode=prefer
is less strict, users should switch tosslmode=verify-full
to keep parity.sslmode=require
is less strict, users should switch tosslmode=verify-full
to keep parity.sslmode=verify-ca
is less strict, users should switch tosslmode=verify-full
to keep parity.Prior discussions about
sslmode
I believe this PR addresses concerns raised in these two GH issues in the past:
#2281
#2009
In particular, there has been one case where the
sslmode=verify-ca
is currently too strict when connecting through AWS RDS Proxy, but the work-around of usingsslmode=no-verify
would disable CA verification completely.Other languages/libraries and their support for
sslmode
Just as a reference, these two libraries are also trying to be more or less consistent with libpq:
disable
,require
,verify-ca
andverify-full
only.Thanks for considering this change and please let me know how I can polish this further for acceptance 🙏