From 759354922a6624524da0c7b935ec77e89f9408da Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 11 Jul 2025 16:33:54 +0200 Subject: [PATCH 1/2] Use certifi certificates if available We're using nodeenv to set up node on various HPC systems, and we already use certifi. Tools that use urllib3 work out of the box with certifi, but for urllib2 this is needed for certifi certificates to be picked up. --- nodeenv.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/nodeenv.py b/nodeenv.py index bccdfee..eeb016a 100644 --- a/nodeenv.py +++ b/nodeenv.py @@ -649,7 +649,15 @@ def urlopen(url): context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_NONE return urllib2.urlopen(req, context=context) - return urllib2.urlopen(req) + + # Use certifi certificates if available + try: + import certifi + context = ssl.create_default_context(cafile=certifi.where()) + return urllib2.urlopen(req, context=context) + except ImportError: + # Fall back to default behavior if certifi is not available + return urllib2.urlopen(req) # --------------------------------------------------------- # Virtual environment functions From a5dc9561662794209008d4c6a14616a734ab0675 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 11 Jul 2025 16:48:21 +0200 Subject: [PATCH 2/2] Add a flag to use certifi certificates Defaults to not using certifi --- nodeenv.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/nodeenv.py b/nodeenv.py index eeb016a..58d619c 100644 --- a/nodeenv.py +++ b/nodeenv.py @@ -59,6 +59,7 @@ is_CYGWIN = platform.system().startswith(('CYGWIN', 'MSYS')) ignore_ssl_certs = False +use_certifi = False # --------------------------------------------------------- # Utils @@ -368,6 +369,11 @@ def make_parser(): action='store_true', default=Config.ignore_ssl_certs, help='Ignore certificates for package downloads. - UNSAFE -') + parser.add_argument( + '--with-certifi', dest='with_certifi', + action='store_true', default=False, + help='Use certifi certificate bundle if available') + parser.add_argument( metavar='DEST_DIR', dest='env_dir', nargs='?', help='Destination directory') @@ -650,14 +656,18 @@ def urlopen(url): context.verify_mode = ssl.CERT_NONE return urllib2.urlopen(req, context=context) - # Use certifi certificates if available - try: - import certifi - context = ssl.create_default_context(cafile=certifi.where()) - return urllib2.urlopen(req, context=context) - except ImportError: - # Fall back to default behavior if certifi is not available - return urllib2.urlopen(req) + # Use certifi certificates if available and requested + if use_certifi: + try: + import certifi + context = ssl.create_default_context(cafile=certifi.where()) + return urllib2.urlopen(req, context=context) + except ImportError: + # Fall back to default behavior if certifi is not available + pass + + # Default behavior without certifi + return urllib2.urlopen(req) # --------------------------------------------------------- # Virtual environment functions @@ -1126,8 +1136,10 @@ def main(): global src_base_url global ignore_ssl_certs + global use_certifi ignore_ssl_certs = args.ignore_ssl_certs + use_certifi = args.with_certifi src_domain = None if args.mirror: